Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Featherless integration #1521

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"electron": "^22.3.13",
"electron-builder": "^24.13.3",
"electron-devtools-installer": "^3.2.0",
"electron-reload": "^2.0.0-alpha.1",
"electronmon": "^2.0.2",
"eslint": "^8.42.0",
"eslint-config-airbnb-base": "^15.0.0",
Expand Down
88 changes: 41 additions & 47 deletions src/renderer/components/AIProviderSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { Chip, MenuItem, Typography } from '@mui/material'
import { ModelProvider, ModelSettings } from '../../shared/types'
import { useTranslation } from 'react-i18next'
import { AIModelProviderMenuOptionList } from '../packages/models'
import * as React from 'react';
import Button from '@mui/material/Button';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import StyledMenu from './StyledMenu';
import StarIcon from '@mui/icons-material/Star';
import * as React from 'react'
import Button from '@mui/material/Button'
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'
import StyledMenu from './StyledMenu'
import StarIcon from '@mui/icons-material/Star'

interface ModelConfigProps {
settings: ModelSettings
Expand All @@ -19,29 +19,25 @@ export default function AIProviderSelect(props: ModelConfigProps) {
const { settings, setSettings, className, hideCustomProviderManage } = props
const { t } = useTranslation()

const [menuAnchorEl, setMenuAnchorEl] = React.useState<null | HTMLElement>(null);
const menuState = Boolean(menuAnchorEl);
const [menuAnchorEl, setMenuAnchorEl] = React.useState<null | HTMLElement>(null)
const menuState = Boolean(menuAnchorEl)
const openMenu = (event: React.MouseEvent<HTMLElement>) => {
setMenuAnchorEl(event.currentTarget);
};
setMenuAnchorEl(event.currentTarget)
}
const closeMenu = () => {
setMenuAnchorEl(null);
};
setMenuAnchorEl(null)
}

return (
<>
<Typography variant='caption' className='opacity-50'>
<Typography variant="caption" className="opacity-50">
{t('Model Provider')}:
</Typography>
<div className='flex items-end justify-between'>
<Button
variant="contained"
disableElevation
onClick={openMenu}
endIcon={<KeyboardArrowDownIcon />}
>
<Typography className='text-left' maxWidth={200} noWrap>
{ AIModelProviderMenuOptionList.find((provider) => provider.value === settings.aiProvider)?.label || 'Unknown' }
<div className="flex items-end justify-between">
<Button variant="contained" disableElevation onClick={openMenu} endIcon={<KeyboardArrowDownIcon />}>
<Typography className="text-left" maxWidth={200} noWrap>
{AIModelProviderMenuOptionList.find((provider) => provider.value === settings.aiProvider)
?.label || 'Unknown'}
</Typography>
</Button>
<StyledMenu
Expand All @@ -57,34 +53,32 @@ export default function AIProviderSelect(props: ModelConfigProps) {
horizontal: 'left',
}}
>
{
AIModelProviderMenuOptionList.map((provider) => (
<MenuItem disableRipple
onClick={() => {
setSettings({
...settings,
aiProvider: provider.value as ModelProvider,
})
closeMenu()
}}
>
<StarIcon />
{provider.label}
{provider.featured && (
<Chip
label={t('Easy Access')}
size="small"
color="success"
variant="outlined"
sx={{ marginLeft: '10px' }}
/>
)}
</MenuItem>
))
}
{AIModelProviderMenuOptionList.map((provider) => (
<MenuItem
disableRipple
onClick={() => {
setSettings({
...settings,
aiProvider: provider.value as ModelProvider,
})
closeMenu()
}}
>
<StarIcon />
{provider.label}
{provider.featured && (
<Chip
label={t('Easy Access')}
size="small"
color="success"
variant="outlined"
sx={{ marginLeft: '10px' }}
/>
)}
</MenuItem>
))}
</StyledMenu>
</div>
</>
)
}

3 changes: 1 addition & 2 deletions src/renderer/components/Accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ export const Accordion = styled((props: AccordionProps) => (
<MuiAccordion disableGutters elevation={0} square {...props} />
))(({ theme }) => ({
border: `1px solid ${theme.palette.divider}`,
'&:not(:last-child)': {
},
'&:not(:last-child)': {},
'&:before': {
display: 'none',
},
Expand Down
49 changes: 49 additions & 0 deletions src/renderer/components/FeatherlessModelSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Select, MenuItem, FormControl, InputLabel, TextField } from '@mui/material'
import { ModelSettings } from '../../shared/types'
import { useTranslation } from 'react-i18next'
import { models } from '../packages/models/featherlessai'

export interface Props {
model: ModelSettings['featherlessModel']
featherlessCustomModel: ModelSettings['featherlessCustomModel']
onChange(
model: ModelSettings['featherlessModel'],
featherlessCustomModel: ModelSettings['featherlessCustomModel']
): void
className?: string
}

export default function FeatherlessModelSelect(props: Props) {
const { t } = useTranslation()
return (
<FormControl fullWidth variant="outlined" margin="dense" className={props.className}>
<InputLabel htmlFor="model-select">{t('model')}</InputLabel>
<Select
label={t('model')}
id="model-select"
value={props.model}
onChange={(e) => props.onChange(e.target.value as ModelSettings['featherlessModel'], props.model)}
>
{models.map((model) => (
<MenuItem key={model} value={model}>
{model}
</MenuItem>
))}
<MenuItem key="custom-model" value={'custom-model'}>
{t('Custom Model')}
</MenuItem>
</Select>
{props.model === 'custom-model' && (
<TextField
margin="dense"
label={t('Custom Model Name')}
type="text"
fullWidth
variant="outlined"
value={props.featherlessCustomModel || ''}
onChange={(e) => props.onChange(props.model, e.target.value.trim())}
/>
)}
</FormControl>
)
}
9 changes: 3 additions & 6 deletions src/renderer/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,17 @@ import * as sessionActions from '../stores/sessionActions'
import Toolbar from './Toolbar'
import { cn } from '@/lib/utils'

interface Props { }
interface Props {}

export default function Header(props: Props) {
const theme = useTheme()
const currentSession = useAtomValue(atoms.currentSessionAtom)
const setChatConfigDialogSession = useSetAtom(atoms.chatConfigDialogAtom)

useEffect(() => {
if (
currentSession.name === 'Untitled'
&& currentSession.messages.length >= 2
) {
if (currentSession.name === 'Untitled' && currentSession.messages.length >= 2) {
sessionActions.generateName(currentSession.id)
return
return
}
}, [currentSession.messages.length])

Expand Down
51 changes: 24 additions & 27 deletions src/renderer/components/InputBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ import { useTranslation } from 'react-i18next'
import * as atoms from '../stores/atoms'
import { useSetAtom } from 'jotai'
import * as sessionActions from '../stores/sessionActions'
import {
SendHorizontal,
Settings2,
} from 'lucide-react'
import { SendHorizontal, Settings2 } from 'lucide-react'
import { cn } from '@/lib/utils'
import icon from '../static/icon.png'
import { trackingEvent } from '@/packages/event'
Expand Down Expand Up @@ -50,13 +47,7 @@ export default function InputBox(props: Props) {
}

const onKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (
event.keyCode === 13 &&
!event.shiftKey &&
!event.ctrlKey &&
!event.altKey &&
!event.metaKey
) {
if (event.keyCode === 13 && !event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey) {
event.preventDefault()
handleSubmit()
return
Expand All @@ -71,38 +62,44 @@ export default function InputBox(props: Props) {
const [easterEgg, setEasterEgg] = useState(false)

return (
<div className='pl-2 pr-4'
<div
className="pl-2 pr-4"
style={{
borderTopWidth: '1px',
borderTopStyle: 'solid',
borderTopColor: theme.palette.divider,
}}
>
<div className={cn('w-full mx-auto flex flex-col')}>
<div className='flex flex-row flex-nowrap justify-between py-1'>
<div className='flex flex-row items-center'>
<MiniButton className='mr-2 hover:bg-transparent' style={{ color: theme.palette.text.primary }}
<div className="flex flex-row flex-nowrap justify-between py-1">
<div className="flex flex-row items-center">
<MiniButton
className="mr-2 hover:bg-transparent"
style={{ color: theme.palette.text.primary }}
onClick={() => {
setEasterEgg(true)
setTimeout(() => setEasterEgg(false), 1000)
}}
>
<img className={cn('w-5 h-5', easterEgg ? 'animate-spin' : '')} src={icon} />
</MiniButton>
<MiniButton className='mr-2' style={{ color: theme.palette.text.primary }}
<MiniButton
className="mr-2"
style={{ color: theme.palette.text.primary }}
onClick={() => setChatConfigDialogSession(sessionActions.getCurrentSession())}
tooltipTitle={
<div className='text-center inline-block'>
<div className="text-center inline-block">
<span>{t('Customize settings for the current conversation')}</span>
</div>
}
tooltipPlacement='top'
tooltipPlacement="top"
>
<Settings2 size='22' strokeWidth={1} />
<Settings2 size="22" strokeWidth={1} />
</MiniButton>
</div>
<div className='flex flex-row items-center'>
<MiniButton className='w-8 ml-2'
<div className="flex flex-row items-center">
<MiniButton
className="w-8 ml-2"
style={{
color: theme.palette.getContrastText(theme.palette.primary.main),
backgroundColor: theme.palette.primary.main,
Expand All @@ -112,21 +109,22 @@ export default function InputBox(props: Props) {
{t('[Enter] send, [Shift+Enter] line break, [Ctrl+Enter] send without generating')}
</Typography>
}
tooltipPlacement='top'
tooltipPlacement="top"
onClick={() => handleSubmit()}
>
<SendHorizontal size='22' strokeWidth={1} />
<SendHorizontal size="22" strokeWidth={1} />
</MiniButton>
</div>
</div>
<div className='w-full pl-1 pb-2'>
<div className="w-full pl-1 pb-2">
<textarea
className={cn(
`w-full max-h-[${maxTextareaHeight}px]`,
'overflow-y resize-none border-none outline-none',
'bg-transparent p-1'
)}
value={messageInput} onChange={onMessageInput}
value={messageInput}
onChange={onMessageInput}
onKeyDown={onKeyDown}
ref={inputRef}
style={{
Expand All @@ -138,8 +136,7 @@ export default function InputBox(props: Props) {
}}
placeholder={t('Type your question here...') || ''}
/>
<div className='flex flex-row items-center'>
</div>
<div className="flex flex-row items-center"></div>
</div>
</div>
</div>
Expand Down
Loading