Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
D
dify
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ai-tech
dify
Commits
1c5f63de
Unverified
Commit
1c5f63de
authored
May 23, 2023
by
zxhlyh
Committed by
GitHub
May 23, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: azure-openai key validate (#164)
parent
f3219ff1
Changes
9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
253 additions
and
385 deletions
+253
-385
index.tsx
...er/account-setting/provider-page/azure-provider/index.tsx
+55
-14
index.tsx
...components/header/account-setting/provider-page/index.tsx
+1
-1
index.tsx
...r/account-setting/provider-page/openai-provider/index.tsx
+71
-199
provider.tsx
...ccount-setting/provider-page/openai-provider/provider.tsx
+0
-52
Validate.tsx
...account-setting/provider-page/provider-input/Validate.tsx
+59
-0
index.tsx
...er/account-setting/provider-page/provider-input/index.tsx
+8
-95
useValidateToken.ts
...-setting/provider-page/provider-input/useValidateToken.ts
+21
-8
index.tsx
...der/account-setting/provider-page/provider-item/index.tsx
+18
-7
common.ts
web/models/common.ts
+20
-9
No files found.
web/app/components/header/account-setting/provider-page/azure-provider/index.tsx
View file @
1c5f63de
import
type
{
Provider
,
ProviderAzureToken
}
from
'@/models/common'
import
{
ProviderName
}
from
'@/models/common'
import
{
useTranslation
}
from
'react-i18next'
import
Link
from
'next/link'
import
{
ArrowTopRightOnSquareIcon
}
from
'@heroicons/react/24/outline'
import
ProviderInput
,
{
ProviderValidateTokenInput
}
from
'../provider-input'
import
{
useState
}
from
'react'
import
{
ValidatedStatus
}
from
'../provider-input/useValidateToken'
import
{
useState
,
useEffect
}
from
'react'
import
ProviderInput
from
'../provider-input'
import
useValidateToken
,
{
ValidatedStatus
}
from
'../provider-input/useValidateToken'
import
{
ValidatedErrorIcon
,
ValidatedSuccessIcon
,
ValidatingTip
,
ValidatedErrorOnAzureOpenaiTip
}
from
'../provider-input/Validate'
interface
IAzureProviderProps
{
provider
:
Provider
...
...
@@ -17,19 +24,51 @@ const AzureProvider = ({
onValidatedStatus
}:
IAzureProviderProps
)
=>
{
const
{
t
}
=
useTranslation
()
const
[
token
,
setToken
]
=
useState
(
provider
.
token
as
ProviderAzureToken
||
{})
const
handleFocus
=
()
=>
{
if
(
token
===
provider
.
token
)
{
token
.
openai_api_key
=
''
const
[
token
,
setToken
]
=
useState
<
ProviderAzureToken
>
(
provider
.
provider_name
===
ProviderName
.
AZURE_OPENAI
?
{...
provider
.
token
}:
{})
const
[
validating
,
validatedStatus
,
setValidatedStatus
,
validate
]
=
useValidateToken
(
provider
.
provider_name
)
const
handleFocus
=
(
type
:
keyof
ProviderAzureToken
)
=>
{
if
(
token
[
type
]
===
(
provider
?.
token
as
ProviderAzureToken
)[
type
])
{
token
[
type
]
=
''
setToken
({...
token
})
onTokenChange
({...
token
})
setValidatedStatus
(
undefined
)
}
}
const
handleChange
=
(
type
:
keyof
ProviderAzureToken
,
v
:
string
)
=>
{
const
handleChange
=
(
type
:
keyof
ProviderAzureToken
,
v
:
string
,
validate
:
any
)
=>
{
token
[
type
]
=
v
setToken
({...
token
})
onTokenChange
({...
token
})
validate
({...
token
},
{
beforeValidating
:
()
=>
{
if
(
!
token
.
openai_api_base
||
!
token
.
openai_api_key
)
{
setValidatedStatus
(
undefined
)
return
false
}
return
true
}
})
}
const
getValidatedIcon
=
()
=>
{
if
(
validatedStatus
===
ValidatedStatus
.
Error
||
validatedStatus
===
ValidatedStatus
.
Exceed
)
{
return
<
ValidatedErrorIcon
/>
}
if
(
validatedStatus
===
ValidatedStatus
.
Success
)
{
return
<
ValidatedSuccessIcon
/>
}
}
const
getValidatedTip
=
()
=>
{
if
(
validating
)
{
return
<
ValidatingTip
/>
}
if
(
validatedStatus
===
ValidatedStatus
.
Error
)
{
return
<
ValidatedErrorOnAzureOpenaiTip
/>
}
}
useEffect
(()
=>
{
if
(
typeof
onValidatedStatus
===
'function'
)
{
onValidatedStatus
(
validatedStatus
)
}
},
[
validatedStatus
])
return
(
<
div
className=
'px-4 py-3'
>
...
...
@@ -38,17 +77,19 @@ const AzureProvider = ({
name=
{
t
(
'common.provider.azure.apiBase'
)
}
placeholder=
{
t
(
'common.provider.azure.apiBasePlaceholder'
)
}
value=
{
token
.
openai_api_base
}
onChange=
{
(
v
)
=>
handleChange
(
'openai_api_base'
,
v
)
}
onChange=
{
(
v
)
=>
handleChange
(
'openai_api_base'
,
v
,
validate
)
}
onFocus=
{
()
=>
handleFocus
(
'openai_api_base'
)
}
validatedIcon=
{
getValidatedIcon
()
}
/>
<
Provider
ValidateToken
Input
<
ProviderInput
className=
'mb-4'
name=
{
t
(
'common.provider.azure.apiKey'
)
}
placeholder=
{
t
(
'common.provider.azure.apiKeyPlaceholder'
)
}
value=
{
token
.
openai_api_key
}
onChange=
{
v
=>
handleChange
(
'openai_api_key'
,
v
)
}
onFocus=
{
handleFocus
}
onValidatedStatus=
{
onValidatedStatus
}
providerName=
{
provider
.
provider_name
}
onChange=
{
(
v
)
=>
handleChange
(
'openai_api_key'
,
v
,
validate
)
}
onFocus=
{
()
=>
handleFocus
(
'openai_api_key'
)
}
validatedIcon=
{
getValidatedIcon
()
}
validatedTip=
{
getValidatedTip
()
}
/>
<
Link
className=
"flex items-center text-xs cursor-pointer text-primary-600"
href=
"https://platform.openai.com/account/api-keys"
target=
{
'_blank'
}
>
{
t
(
'common.provider.azure.helpTip'
)
}
...
...
web/app/components/header/account-setting/provider-page/index.tsx
View file @
1c5f63de
...
...
@@ -67,7 +67,7 @@ const ProviderPage = () => {
const
providerHosted
=
data
?.
filter
(
provider
=>
provider
.
provider_name
===
'openai'
&&
provider
.
provider_type
===
'system'
)?.[
0
]
return
(
<
div
>
<
div
className=
'pb-7'
>
{
providerHosted
&&
!
IS_CE_EDITION
&&
(
<>
...
...
web/app/components/header/account-setting/provider-page/openai-provider/index.tsx
View file @
1c5f63de
This diff is collapsed.
Click to expand it.
web/app/components/header/account-setting/provider-page/openai-provider/provider.tsx
deleted
100644 → 0
View file @
f3219ff1
import
type
{
Provider
}
from
'@/models/common'
import
{
useState
}
from
'react'
import
{
useTranslation
}
from
'react-i18next'
import
{
ProviderValidateTokenInput
}
from
'../provider-input'
import
Link
from
'next/link'
import
{
ArrowTopRightOnSquareIcon
}
from
'@heroicons/react/24/outline'
import
{
ValidatedStatus
}
from
'../provider-input/useValidateToken'
interface
IOpenaiProviderProps
{
provider
:
Provider
onValidatedStatus
:
(
status
?:
ValidatedStatus
)
=>
void
onTokenChange
:
(
token
:
string
)
=>
void
}
const
OpenaiProvider
=
({
provider
,
onValidatedStatus
,
onTokenChange
}:
IOpenaiProviderProps
)
=>
{
const
{
t
}
=
useTranslation
()
const
[
token
,
setToken
]
=
useState
(
provider
.
token
as
string
||
''
)
const
handleFocus
=
()
=>
{
if
(
token
===
provider
.
token
)
{
setToken
(
''
)
onTokenChange
(
''
)
}
}
const
handleChange
=
(
v
:
string
)
=>
{
setToken
(
v
)
onTokenChange
(
v
)
}
return
(
<
div
className=
'px-4 pt-3 pb-4'
>
<
ProviderValidateTokenInput
value=
{
token
}
name=
{
t
(
'common.provider.apiKey'
)
}
placeholder=
{
t
(
'common.provider.enterYourKey'
)
}
onChange=
{
handleChange
}
onFocus=
{
handleFocus
}
onValidatedStatus=
{
onValidatedStatus
}
providerName=
{
provider
.
provider_name
}
/>
<
Link
className=
"inline-flex items-center mt-3 text-xs font-normal cursor-pointer text-primary-600 w-fit"
href=
"https://platform.openai.com/account/api-keys"
target=
{
'_blank'
}
>
{
t
(
'appOverview.welcome.getKeyTip'
)
}
<
ArrowTopRightOnSquareIcon
className=
'w-3 h-3 ml-1 text-primary-600'
aria
-
hidden=
"true"
/>
</
Link
>
</
div
>
)
}
export
default
OpenaiProvider
\ No newline at end of file
web/app/components/header/account-setting/provider-page/provider-input/Validate.tsx
0 → 100644
View file @
1c5f63de
import
Link
from
'next/link'
import
{
CheckCircleIcon
,
ExclamationCircleIcon
}
from
'@heroicons/react/24/solid'
import
{
useTranslation
}
from
'react-i18next'
import
{
useContext
}
from
'use-context-selector'
import
I18n
from
'@/context/i18n'
export
const
ValidatedErrorIcon
=
()
=>
{
return
<
ExclamationCircleIcon
className=
'w-4 h-4 text-[#D92D20]'
/>
}
export
const
ValidatedSuccessIcon
=
()
=>
{
return
<
CheckCircleIcon
className=
'w-4 h-4 text-[#039855]'
/>
}
export
const
ValidatingTip
=
()
=>
{
const
{
t
}
=
useTranslation
()
return
(
<
div
className=
{
`mt-2 text-primary-600 text-xs font-normal`
}
>
{
t
(
'common.provider.validating'
)
}
</
div
>
)
}
export
const
ValidatedExceedOnOpenaiTip
=
()
=>
{
const
{
t
}
=
useTranslation
()
const
{
locale
}
=
useContext
(
I18n
)
return
(
<
div
className=
{
`mt-2 text-[#D92D20] text-xs font-normal`
}
>
{
t
(
'common.provider.apiKeyExceedBill'
)
}
<
Link
className=
'underline'
href=
"https://platform.openai.com/account/api-keys"
target=
{
'_blank'
}
>
{
locale
===
'en'
?
'this link'
:
'这篇文档'
}
</
Link
>
</
div
>
)
}
export
const
ValidatedErrorOnOpenaiTip
=
()
=>
{
const
{
t
}
=
useTranslation
()
return
(
<
div
className=
{
`mt-2 text-[#D92D20] text-xs font-normal`
}
>
{
t
(
'common.provider.invalidKey'
)
}
</
div
>
)
}
export
const
ValidatedErrorOnAzureOpenaiTip
=
()
=>
{
const
{
t
}
=
useTranslation
()
return
(
<
div
className=
{
`mt-2 text-[#D92D20] text-xs font-normal`
}
>
{
t
(
'common.provider.invalidApiKey'
)
}
</
div
>
)
}
\ No newline at end of file
web/app/components/header/account-setting/provider-page/provider-input/index.tsx
View file @
1c5f63de
import
{
ChangeEvent
,
useEffect
}
from
'react'
import
Link
from
'next/link'
import
{
CheckCircleIcon
,
ExclamationCircleIcon
}
from
'@heroicons/react/24/solid'
import
{
useTranslation
}
from
'react-i18next'
import
{
useContext
}
from
'use-context-selector'
import
I18n
from
'@/context/i18n'
import
useValidateToken
,
{
ValidatedStatus
}
from
'./useValidateToken'
import
{
ChangeEvent
}
from
'react'
import
{
ReactElement
}
from
'react-markdown/lib/react-markdown'
interface
IProviderInputProps
{
value
?:
string
...
...
@@ -13,6 +8,8 @@ interface IProviderInputProps {
className
?:
string
onChange
:
(
v
:
string
)
=>
void
onFocus
?:
()
=>
void
validatedIcon
?:
ReactElement
validatedTip
?:
ReactElement
}
const
ProviderInput
=
({
...
...
@@ -22,6 +19,8 @@ const ProviderInput = ({
className
,
onChange
,
onFocus
,
validatedIcon
,
validatedTip
}:
IProviderInputProps
)
=>
{
const
handleChange
=
(
e
:
ChangeEvent
<
HTMLInputElement
>
)
=>
{
...
...
@@ -47,95 +46,9 @@ const ProviderInput = ({
onChange=
{
handleChange
}
onFocus=
{
onFocus
}
/>
{
validatedIcon
}
</
div
>
</
div
>
)
}
type
TproviderInputProps
=
IProviderInputProps
&
{
onValidatedStatus
?:
(
status
?:
ValidatedStatus
)
=>
void
providerName
:
string
}
export
const
ProviderValidateTokenInput
=
({
value
,
name
,
placeholder
,
className
,
onChange
,
onFocus
,
onValidatedStatus
,
providerName
}:
TproviderInputProps
)
=>
{
const
{
t
}
=
useTranslation
()
const
{
locale
}
=
useContext
(
I18n
)
const
[
validating
,
validatedStatus
,
validate
]
=
useValidateToken
(
providerName
)
useEffect
(()
=>
{
if
(
typeof
onValidatedStatus
===
'function'
)
{
onValidatedStatus
(
validatedStatus
)
}
},
[
validatedStatus
])
const
handleChange
=
(
e
:
ChangeEvent
<
HTMLInputElement
>
)
=>
{
const
inputValue
=
e
.
target
.
value
onChange
(
inputValue
)
validate
(
inputValue
)
}
return
(
<
div
className=
{
className
}
>
<
div
className=
"mb-2 text-[13px] font-medium text-gray-800"
>
{
name
}
</
div
>
<
div
className=
'
flex items-center px-3 bg-white rounded-lg
shadow-[0_1px_2px_rgba(16,24,40,0.05)]
'
>
<
input
className=
'
w-full py-[9px]
text-xs font-medium text-gray-700 leading-[18px]
appearance-none outline-none bg-transparent
'
value=
{
value
}
placeholder=
{
placeholder
}
onChange=
{
handleChange
}
onFocus=
{
onFocus
}
/>
{
validatedStatus
===
ValidatedStatus
.
Error
&&
<
ExclamationCircleIcon
className=
'w-4 h-4 text-[#D92D20]'
/>
}
{
validatedStatus
===
ValidatedStatus
.
Success
&&
<
CheckCircleIcon
className=
'w-4 h-4 text-[#039855]'
/>
}
</
div
>
{
validating
&&
(
<
div
className=
{
`mt-2 text-primary-600 text-xs font-normal`
}
>
{
t
(
'common.provider.validating'
)
}
</
div
>
)
}
{
validatedStatus
===
ValidatedStatus
.
Exceed
&&
!
validating
&&
(
<
div
className=
{
`mt-2 text-[#D92D20] text-xs font-normal`
}
>
{
t
(
'common.provider.apiKeyExceedBill'
)
}
<
Link
className=
'underline'
href=
"https://platform.openai.com/account/api-keys"
target=
{
'_blank'
}
>
{
locale
===
'en'
?
'this link'
:
'这篇文档'
}
</
Link
>
</
div
>
)
}
{
validatedStatus
===
ValidatedStatus
.
Error
&&
!
validating
&&
(
<
div
className=
{
`mt-2 text-[#D92D20] text-xs font-normal`
}
>
{
t
(
'common.provider.invalidKey'
)
}
</
div
>
)
}
{
validatedTip
}
</
div
>
)
}
...
...
web/app/components/header/account-setting/provider-page/provider-input/useValidateToken.ts
View file @
1c5f63de
import
{
useState
,
useCallback
}
from
'react'
import
{
useState
,
useCallback
,
SetStateAction
,
Dispatch
}
from
'react'
import
debounce
from
'lodash-es/debounce'
import
{
DebouncedFunc
}
from
'lodash-es'
import
{
validateProviderKey
}
from
'@/service/common'
...
...
@@ -8,14 +8,24 @@ export enum ValidatedStatus {
Error
=
'error'
,
Exceed
=
'exceed'
}
export
type
SetValidatedStatus
=
Dispatch
<
SetStateAction
<
ValidatedStatus
|
undefined
>>
export
type
ValidateFn
=
DebouncedFunc
<
(
token
:
any
,
config
:
ValidateFnConfig
)
=>
void
>
type
ValidateTokenReturn
=
[
boolean
,
ValidatedStatus
|
undefined
,
SetValidatedStatus
,
ValidateFn
]
export
type
ValidateFnConfig
=
{
beforeValidating
:
(
token
:
any
)
=>
boolean
}
const
useValidateToken
=
(
providerName
:
string
):
[
boolean
,
ValidatedStatus
|
undefined
,
DebouncedFunc
<
(
token
:
string
)
=>
Promise
<
void
>>
]
=>
{
const
useValidateToken
=
(
providerName
:
string
):
ValidateTokenReturn
=>
{
const
[
validating
,
setValidating
]
=
useState
(
false
)
const
[
validatedStatus
,
setValidatedStatus
]
=
useState
<
ValidatedStatus
|
undefined
>
()
const
validate
=
useCallback
(
debounce
(
async
(
token
:
string
)
=>
{
if
(
!
token
)
{
setValidatedStatus
(
undefined
)
return
const
validate
=
useCallback
(
debounce
(
async
(
token
:
string
,
config
:
ValidateFnConfig
)
=>
{
if
(
!
config
.
beforeValidating
(
token
))
{
return
false
}
setValidating
(
true
)
try
{
...
...
@@ -24,8 +34,10 @@ const useValidateToken = (providerName: string): [boolean, ValidatedStatus | und
}
catch
(
e
:
any
)
{
if
(
e
.
status
===
400
)
{
e
.
json
().
then
(({
code
}:
any
)
=>
{
if
(
code
===
'provider_request_failed'
)
{
if
(
code
===
'provider_request_failed'
&&
providerName
===
'openai'
)
{
setValidatedStatus
(
ValidatedStatus
.
Exceed
)
}
else
{
setValidatedStatus
(
ValidatedStatus
.
Error
)
}
})
}
else
{
...
...
@@ -39,7 +51,8 @@ const useValidateToken = (providerName: string): [boolean, ValidatedStatus | und
return
[
validating
,
validatedStatus
,
validate
,
setValidatedStatus
,
validate
]
}
...
...
web/app/components/header/account-setting/provider-page/provider-item/index.tsx
View file @
1c5f63de
...
...
@@ -5,7 +5,8 @@ import { useContext } from 'use-context-selector'
import
Indicator
from
'../../../indicator'
import
{
useTranslation
}
from
'react-i18next'
import
type
{
Provider
,
ProviderAzureToken
}
from
'@/models/common'
import
OpenaiProvider
from
'../openai-provider/provider'
import
{
ProviderName
}
from
'@/models/common'
import
OpenaiProvider
from
'../openai-provider'
import
AzureProvider
from
'../azure-provider'
import
{
ValidatedStatus
}
from
'../provider-input/useValidateToken'
import
{
updateProviderAIKey
}
from
'@/service/common'
...
...
@@ -38,13 +39,23 @@ const ProviderItem = ({
)
const
id
=
`
${
provider
.
provider_name
}
-
${
provider
.
provider_type
}
`
const
isOpen
=
id
===
activeId
const
providerKey
=
provider
.
provider_name
===
'azure_openai'
?
(
provider
.
token
as
ProviderAzureToken
)?.
openai_api_key
:
provider
.
token
const
comingSoon
=
false
const
isValid
=
provider
.
is_valid
const
providerTokenHasSetted
=
()
=>
{
if
(
provider
.
provider_name
===
ProviderName
.
AZURE_OPENAI
)
{
return
provider
.
token
&&
provider
.
token
.
openai_api_base
&&
provider
.
token
.
openai_api_key
?
{
openai_api_base
:
provider
.
token
.
openai_api_base
,
openai_api_key
:
provider
.
token
.
openai_api_key
}:
undefined
}
if
(
provider
.
provider_name
===
ProviderName
.
OPENAI
)
{
return
provider
.
token
}
}
const
handleUpdateToken
=
async
()
=>
{
if
(
loading
)
return
if
(
validatedStatus
===
ValidatedStatus
.
Success
||
!
token
)
{
if
(
validatedStatus
===
ValidatedStatus
.
Success
)
{
try
{
setLoading
(
true
)
await
updateProviderAIKey
({
url
:
`/workspaces/current/providers/
${
provider
.
provider_name
}
/token`
,
body
:
{
token
}
})
...
...
@@ -65,7 +76,7 @@ const ProviderItem = ({
<
div
className=
{
cn
(
s
[
`icon-${icon}`
],
'mr-3 w-6 h-6 rounded-md'
)
}
/>
<
div
className=
'grow text-sm font-medium text-gray-800'
>
{
name
}
</
div
>
{
provider
Key
&&
!
comingSoon
&&
!
isOpen
&&
(
provider
TokenHasSetted
()
&&
!
comingSoon
&&
!
isOpen
&&
(
<
div
className=
'flex items-center mr-4'
>
{
!
isValid
&&
<
div
className=
'text-xs text-[#D92D20]'
>
{
t
(
'common.provider.invalidApiKey'
)
}
</
div
>
}
<
Indicator
color=
{
!
isValid
?
'red'
:
'green'
}
className=
'ml-2'
/>
...
...
@@ -78,7 +89,7 @@ const ProviderItem = ({
px-3 h-[28px] bg-white border border-gray-200 rounded-md cursor-pointer
text-xs font-medium text-gray-700 flex items-center
'
onClick=
{
()
=>
onActive
(
id
)
}
>
{
provider
Key
?
t
(
'common.provider.editKey'
)
:
t
(
'common.provider.addKey'
)
}
{
provider
TokenHasSetted
()
?
t
(
'common.provider.editKey'
)
:
t
(
'common.provider.addKey'
)
}
</
div
>
)
}
...
...
@@ -114,7 +125,7 @@ const ProviderItem = ({
}
</
div
>
{
provider
.
provider_name
===
'openai'
&&
isOpen
&&
(
provider
.
provider_name
===
ProviderName
.
OPENAI
&&
isOpen
&&
(
<
OpenaiProvider
provider=
{
provider
}
onValidatedStatus=
{
v
=>
setValidatedStatus
(
v
)
}
...
...
@@ -123,7 +134,7 @@ const ProviderItem = ({
)
}
{
provider
.
provider_name
===
'azure_openai'
&&
isOpen
&&
(
provider
.
provider_name
===
ProviderName
.
AZURE_OPENAI
&&
isOpen
&&
(
<
AzureProvider
provider=
{
provider
}
onValidatedStatus=
{
v
=>
setValidatedStatus
(
v
)
}
...
...
web/models/common.ts
View file @
1c5f63de
...
...
@@ -54,18 +54,29 @@ export type Member = Pick<UserProfileResponse, 'id' | 'name' | 'email' | 'last_l
role
:
'owner'
|
'admin'
|
'normal'
}
export
enum
ProviderName
{
OPENAI
=
'openai'
,
AZURE_OPENAI
=
'azure_openai'
}
export
type
ProviderAzureToken
=
{
openai_api_base
:
string
openai_api_key
:
string
openai_api_base
?
:
string
openai_api_key
?
:
string
}
export
type
Provider
=
{
provider_name
:
string
provider_type
:
string
is_valid
:
boolean
is_enabled
:
boolean
last_used
:
string
token
?:
string
|
ProviderAzureToken
export
type
ProviderTokenType
=
{
[
ProviderName
.
OPENAI
]:
string
[
ProviderName
.
AZURE_OPENAI
]:
ProviderAzureToken
}
export
type
Provider
=
{
[
Name
in
ProviderName
]:
{
provider_name
:
Name
}
&
{
provider_type
:
'custom'
|
'system'
is_valid
:
boolean
is_enabled
:
boolean
last_used
:
string
token
?:
ProviderTokenType
[
Name
]
}
}[
ProviderName
]
export
type
ProviderHosted
=
Provider
&
{
quota_type
:
string
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment