-
Notifications
You must be signed in to change notification settings - Fork 9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: frontend support claude (#573)
Co-authored-by: StyleZhang <[email protected]>
- Loading branch information
Showing
17 changed files
with
401 additions
and
35 deletions.
There are no files selected for viewing
72 changes: 53 additions & 19 deletions
72
web/app/components/app/configuration/config-model/index.tsx
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
...omponents/header/account-setting/provider-page/anthropic-hosted-provider/index.module.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
.icon { | ||
width: 24px; | ||
height: 24px; | ||
margin-right: 12px; | ||
background: url(../../../assets/anthropic.svg) center center no-repeat; | ||
background-size: contain; | ||
} | ||
|
||
.bar { | ||
background: linear-gradient(90deg, rgba(41, 112, 255, 0.9) 0%, rgba(21, 94, 239, 0.9) 100%); | ||
} | ||
|
||
.bar-error { | ||
background: linear-gradient(90deg, rgba(240, 68, 56, 0.72) 0%, rgba(217, 45, 32, 0.9) 100%); | ||
} | ||
|
||
.bar-item { | ||
width: 10%; | ||
border-right: 1px solid rgba(255, 255, 255, 0.5); | ||
} | ||
|
||
.bar-item:last-of-type { | ||
border-right: 0; | ||
} |
65 changes: 65 additions & 0 deletions
65
web/app/components/header/account-setting/provider-page/anthropic-hosted-provider/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { useTranslation } from 'react-i18next' | ||
import cn from 'classnames' | ||
import s from './index.module.css' | ||
import type { ProviderHosted } from '@/models/common' | ||
|
||
type AnthropicHostedProviderProps = { | ||
provider: ProviderHosted | ||
} | ||
const AnthropicHostedProvider = ({ | ||
provider, | ||
}: AnthropicHostedProviderProps) => { | ||
const { t } = useTranslation() | ||
const exhausted = provider.quota_used > provider.quota_limit | ||
|
||
return ( | ||
<div className={` | ||
border-[0.5px] border-gray-200 rounded-xl | ||
${exhausted ? 'bg-[#FFFBFA]' : 'bg-gray-50'} | ||
`}> | ||
<div className='pt-4 px-4 pb-3'> | ||
<div className='flex items-center mb-3'> | ||
<div className={s.icon} /> | ||
<div className='grow text-sm font-medium text-gray-800'> | ||
{t('common.provider.anthropicHosted.anthropicHosted')} | ||
</div> | ||
<div className={` | ||
px-2 h-[22px] flex items-center rounded-md border | ||
text-xs font-semibold | ||
${exhausted ? 'border-[#D92D20] text-[#D92D20]' : 'border-primary-600 text-primary-600'} | ||
`}> | ||
{exhausted ? t('common.provider.anthropicHosted.exhausted') : t('common.provider.anthropicHosted.onTrial')} | ||
</div> | ||
</div> | ||
<div className='text-[13px] text-gray-500'>{t('common.provider.anthropicHosted.desc')}</div> | ||
</div> | ||
<div className='flex items-center h-[42px] px-4 border-t-[0.5px] border-t-[rgba(0, 0, 0, 0.05)]'> | ||
<div className='text-[13px] text-gray-700'>{t('common.provider.anthropicHosted.callTimes')}</div> | ||
<div className='relative grow h-2 flex bg-gray-200 rounded-md mx-2 overflow-hidden'> | ||
<div | ||
className={cn(s.bar, exhausted && s['bar-error'], 'absolute top-0 left-0 right-0 bottom-0')} | ||
style={{ width: `${(provider.quota_used / provider.quota_limit * 100).toFixed(2)}%` }} | ||
/> | ||
{Array(10).fill(0).map((i, k) => ( | ||
<div key={k} className={s['bar-item']} /> | ||
))} | ||
</div> | ||
<div className={` | ||
text-[13px] font-medium ${exhausted ? 'text-[#D92D20]' : 'text-gray-700'} | ||
`}>{provider.quota_used}/{provider.quota_limit}</div> | ||
</div> | ||
{ | ||
exhausted && ( | ||
<div className=' | ||
px-4 py-3 leading-[18px] flex items-center text-[13px] text-gray-700 font-medium | ||
bg-[#FFFAEB] border-t border-t-[rgba(0, 0, 0, 0.05)] rounded-b-xl | ||
'> | ||
{t('common.provider.anthropicHosted.usedUp')} | ||
</div> | ||
) | ||
} | ||
</div> | ||
) | ||
} | ||
|
||
export default AnthropicHostedProvider |
Empty file.
90 changes: 90 additions & 0 deletions
90
web/app/components/header/account-setting/provider-page/anthropic-provider/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { useEffect, useState } from 'react' | ||
import { useTranslation } from 'react-i18next' | ||
import Link from 'next/link' | ||
import { ArrowTopRightOnSquareIcon } from '@heroicons/react/24/outline' | ||
import ProviderInput from '../provider-input' | ||
import type { ValidatedStatusState } from '../provider-input/useValidateToken' | ||
import useValidateToken, { ValidatedStatus } from '../provider-input/useValidateToken' | ||
import { | ||
ValidatedErrorIcon, | ||
ValidatedErrorOnOpenaiTip, | ||
ValidatedSuccessIcon, | ||
ValidatingTip, | ||
} from '../provider-input/Validate' | ||
import type { Provider, ProviderAnthropicToken } from '@/models/common' | ||
|
||
type AnthropicProviderProps = { | ||
provider: Provider | ||
onValidatedStatus: (status?: ValidatedStatusState) => void | ||
onTokenChange: (token: ProviderAnthropicToken) => void | ||
} | ||
|
||
const AnthropicProvider = ({ | ||
provider, | ||
onValidatedStatus, | ||
onTokenChange, | ||
}: AnthropicProviderProps) => { | ||
const { t } = useTranslation() | ||
const [token, setToken] = useState<ProviderAnthropicToken>((provider.token as ProviderAnthropicToken) || { anthropic_api_key: '' }) | ||
const [validating, validatedStatus, setValidatedStatus, validate] = useValidateToken(provider.provider_name) | ||
const handleFocus = () => { | ||
if (token.anthropic_api_key === (provider.token as ProviderAnthropicToken).anthropic_api_key) { | ||
setToken({ anthropic_api_key: '' }) | ||
onTokenChange({ anthropic_api_key: '' }) | ||
setValidatedStatus({}) | ||
} | ||
} | ||
const handleChange = (v: string) => { | ||
const apiKey = { anthropic_api_key: v } | ||
setToken(apiKey) | ||
onTokenChange(apiKey) | ||
validate(apiKey, { | ||
beforeValidating: () => { | ||
if (!v) { | ||
setValidatedStatus({}) | ||
return false | ||
} | ||
return true | ||
}, | ||
}) | ||
} | ||
useEffect(() => { | ||
if (typeof onValidatedStatus === 'function') | ||
onValidatedStatus(validatedStatus) | ||
}, [validatedStatus]) | ||
|
||
const getValidatedIcon = () => { | ||
if (validatedStatus?.status === ValidatedStatus.Error || validatedStatus.status === ValidatedStatus.Exceed) | ||
return <ValidatedErrorIcon /> | ||
|
||
if (validatedStatus.status === ValidatedStatus.Success) | ||
return <ValidatedSuccessIcon /> | ||
} | ||
const getValidatedTip = () => { | ||
if (validating) | ||
return <ValidatingTip /> | ||
|
||
if (validatedStatus?.status === ValidatedStatus.Error) | ||
return <ValidatedErrorOnOpenaiTip errorMessage={validatedStatus.message ?? ''} /> | ||
} | ||
|
||
return ( | ||
<div className='px-4 pt-3 pb-4'> | ||
<ProviderInput | ||
value={token.anthropic_api_key} | ||
name={t('common.provider.apiKey')} | ||
placeholder={t('common.provider.enterYourKey')} | ||
onChange={handleChange} | ||
onFocus={handleFocus} | ||
validatedIcon={getValidatedIcon()} | ||
validatedTip={getValidatedTip()} | ||
/> | ||
<Link className="inline-flex items-center mt-3 text-xs font-normal cursor-pointer text-primary-600 w-fit" href="https://docs.anthropic.com/claude/reference/getting-started-with-the-api" target={'_blank'}> | ||
{t('common.provider.anthropic.keyFrom')} | ||
<ArrowTopRightOnSquareIcon className='w-3 h-3 ml-1 text-primary-600' aria-hidden="true" /> | ||
</Link> | ||
</div> | ||
) | ||
} | ||
|
||
export default AnthropicProvider |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.