refactor: update model attribute references from 'model' to 'model_name' across multiple files and introduce new fetch_model_config function in llm_utils.py

This commit is contained in:
Novice
2026-03-23 21:17:43 +08:00
parent ee81ea882b
commit ed1bd338f1
23 changed files with 640 additions and 175 deletions

View File

@ -3,6 +3,7 @@ export const ACCOUNT_SETTING_MODAL_ACTION = 'showSettings'
export const ACCOUNT_SETTING_TAB = {
SANDBOX_PROVIDER: 'sandbox-provider',
MODEL_PROVIDER: 'model-provider',
PROVIDER: 'model-provider',
MEMBERS: 'members',
BILLING: 'billing',
DATA_SOURCE: 'data-source',

View File

@ -32,6 +32,7 @@ import Trigger from './trigger'
export type ModelParameterModalProps = {
popupClassName?: string
portalToFollowElemContentClassName?: string
isAdvancedMode: boolean
modelId: string
provider: string

View File

@ -19,6 +19,7 @@ import {
export type TriggerProps = {
open?: boolean
disabled?: boolean
currentProvider?: ModelProvider | Model
currentModel?: ModelItem
providerName?: string

View File

@ -7,9 +7,9 @@ import { useTranslation } from 'react-i18next'
import Button from '@/app/components/base/button'
import { BaseForm } from '@/app/components/base/form/components/base'
import { FormTypeEnum } from '@/app/components/base/form/types'
import Modal from '@/app/components/base/modal'
import RadioUI from '@/app/components/base/radio/ui'
import { useToastContext } from '@/app/components/base/toast/context'
import { Dialog, DialogCloseButton, DialogContent } from '@/app/components/base/ui/dialog'
import { toast } from '@/app/components/base/ui/toast'
import {
useActivateSandboxProvider,
useDeleteSandboxProviderConfig,
@ -21,7 +21,6 @@ import ProviderIcon from './provider-icon'
type ConfigMode = 'managed' | 'byok'
// Providers that support mode selection (must have system config available)
const PROVIDERS_WITH_MODE_SELECTION: readonly string[] = ['e2b']
type ModeOptionProps = {
@ -64,20 +63,16 @@ type ConfigModalProps = {
function ConfigModal({ provider, onClose }: ConfigModalProps) {
const { t } = useTranslation()
const { notify } = useToastContext()
const formRef = useRef<FormRefObject>(null)
const { mutateAsync: saveConfig, isPending: isSaving } = useSaveSandboxProviderConfig()
const { mutateAsync: deleteConfig, isPending: isDeleting } = useDeleteSandboxProviderConfig()
const { mutateAsync: activateProvider, isPending: isActivating } = useActivateSandboxProvider()
// Determine if mode selection should be shown (for providers that support it)
const shouldShowModeSelection = PROVIDERS_WITH_MODE_SELECTION.includes(provider.provider_type)
// Managed mode is only available when system has configured this provider
const isManagedModeAvailable = provider.is_system_configured
// Determine default mode based on configuration state
const defaultMode: ConfigMode = provider.is_tenant_configured
? 'byok'
: provider.is_system_configured
@ -105,11 +100,10 @@ function ConfigModal({ provider, onClose }: ConfigModalProps) {
}, [provider.config_schema, provider.config, t])
const handleSave = useCallback(async () => {
// For managed mode, activate system config (preserves user config for future use)
if (shouldShowModeSelection && configMode === 'managed') {
try {
await activateProvider({ providerType: provider.provider_type, type: 'system' })
notify({ type: 'success', message: t('api.saved', { ns: 'common' }) })
toast.success(t('api.saved', { ns: 'common' }))
onClose()
}
catch {
@ -118,7 +112,6 @@ function ConfigModal({ provider, onClose }: ConfigModalProps) {
return
}
// For BYOK mode, validate and save user-provided config
const formValues = formRef.current?.getFormValues({
needTransformWhenSecretFieldIsPristine: true,
})
@ -132,124 +125,126 @@ function ConfigModal({ provider, onClose }: ConfigModalProps) {
config: formValues.values,
activate: true,
})
notify({ type: 'success', message: t('api.saved', { ns: 'common' }) })
toast.success(t('api.saved', { ns: 'common' }))
onClose()
}
catch {
// Error toast is handled by fetch layer
}
}, [shouldShowModeSelection, configMode, saveConfig, activateProvider, provider.provider_type, notify, t, onClose])
}, [shouldShowModeSelection, configMode, saveConfig, activateProvider, provider.provider_type, t, onClose])
const handleRevoke = useCallback(async () => {
try {
await deleteConfig(provider.provider_type)
notify({ type: 'success', message: t('api.remove', { ns: 'common' }) })
toast.success(t('api.remove', { ns: 'common' }))
onClose()
}
catch {
// Error toast is handled by fetch layer
}
}, [deleteConfig, provider.provider_type, notify, t, onClose])
}, [deleteConfig, provider.provider_type, t, onClose])
const docLink = PROVIDER_DOC_LINKS[provider.provider_type]
const providerLabel = PROVIDER_STATIC_LABELS[provider.provider_type as keyof typeof PROVIDER_STATIC_LABELS]
?? provider.provider_type
// Only show revoke button when in BYOK mode, tenant has custom config, and provider is not active
// (active provider cannot be revoked to prevent "no sandbox provider" error)
const showRevokeButton = provider.is_tenant_configured && !provider.is_active && (!shouldShowModeSelection || configMode === 'byok')
const isActionDisabled = isSaving || isDeleting || isActivating
const showByokForm = !shouldShowModeSelection || configMode === 'byok'
return (
<Modal isShow onClose={onClose} closable className="w-[480px]">
{/* Header */}
<div className="mb-4 flex flex-col gap-2">
<h3 className="text-text-primary title-2xl-semi-bold">
{t('sandboxProvider.configModal.title', { ns: 'common' })}
</h3>
<div className="flex items-center gap-2">
<ProviderIcon providerType={provider.provider_type} size="sm" withBorder />
<span className="text-text-secondary system-md-regular">{providerLabel}</span>
</div>
</div>
<Dialog open onOpenChange={open => !open && onClose()}>
<DialogContent className="w-[480px]">
<DialogCloseButton />
{/* Mode Selection */}
{shouldShowModeSelection && (
<div className="mb-4 flex flex-col gap-1">
<label className="text-text-secondary system-sm-medium">
{t('sandboxProvider.configModal.connectionMode', { ns: 'common' })}
</label>
<div className="flex flex-col gap-2">
<ModeOption
isSelected={configMode === 'managed'}
isDisabled={!isManagedModeAvailable}
title={t('sandboxProvider.configModal.managedByDify', { ns: 'common' })}
description={t('sandboxProvider.configModal.managedByDifyDesc', { ns: 'common' })}
onClick={() => setConfigMode('managed')}
/>
<ModeOption
isSelected={configMode === 'byok'}
title={t('sandboxProvider.configModal.bringYourOwnKey', { ns: 'common' })}
description={t('sandboxProvider.configModal.bringYourOwnKeyDesc', { ns: 'common' })}
onClick={() => setConfigMode('byok')}
/>
{/* Header */}
<div className="mb-4 flex flex-col gap-2">
<h3 className="text-text-primary title-2xl-semi-bold">
{t('sandboxProvider.configModal.title', { ns: 'common' })}
</h3>
<div className="flex items-center gap-2">
<ProviderIcon providerType={provider.provider_type} size="sm" withBorder />
<span className="text-text-secondary system-md-regular">{providerLabel}</span>
</div>
</div>
)}
{/* Form fields (hidden when managed mode is selected) */}
{showByokForm && (
<BaseForm
formSchemas={formSchemas}
ref={formRef}
labelClassName="system-sm-medium mb-1 flex items-center gap-1 text-text-secondary"
formClassName="space-y-4"
/>
)}
{/* Mode Selection */}
{shouldShowModeSelection && (
<div className="mb-4 flex flex-col gap-1">
<label className="text-text-secondary system-sm-medium">
{t('sandboxProvider.configModal.connectionMode', { ns: 'common' })}
</label>
<div className="flex flex-col gap-2">
<ModeOption
isSelected={configMode === 'managed'}
isDisabled={!isManagedModeAvailable}
title={t('sandboxProvider.configModal.managedByDify', { ns: 'common' })}
description={t('sandboxProvider.configModal.managedByDifyDesc', { ns: 'common' })}
onClick={() => setConfigMode('managed')}
/>
<ModeOption
isSelected={configMode === 'byok'}
title={t('sandboxProvider.configModal.bringYourOwnKey', { ns: 'common' })}
description={t('sandboxProvider.configModal.bringYourOwnKeyDesc', { ns: 'common' })}
onClick={() => setConfigMode('byok')}
/>
</div>
</div>
)}
{/* Footer Actions */}
<div className="mt-6 flex items-center justify-between">
<div>
{docLink && (
<a
href={docLink}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 text-text-accent system-xs-regular hover:underline"
>
{t('sandboxProvider.configModal.readDocLink', { ns: 'common', provider: providerLabel })}
<span className="i-ri-external-link-line h-3 w-3" />
</a>
)}
</div>
<div className="flex items-center gap-2">
{showRevokeButton && (
<Button variant="warning" size="medium" onClick={handleRevoke} disabled={isActionDisabled}>
{t('sandboxProvider.configModal.revoke', { ns: 'common' })}
{/* Form fields */}
{showByokForm && (
<BaseForm
formSchemas={formSchemas}
ref={formRef}
labelClassName="system-sm-medium mb-1 flex items-center gap-1 text-text-secondary"
formClassName="space-y-4"
/>
)}
{/* Footer Actions */}
<div className="mt-6 flex items-center justify-between">
<div>
{docLink && (
<a
href={docLink}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 text-text-accent system-xs-regular hover:underline"
>
{t('sandboxProvider.configModal.readDocLink', { ns: 'common', provider: providerLabel })}
<span className="i-ri-external-link-line h-3 w-3" />
</a>
)}
</div>
<div className="flex items-center gap-2">
{showRevokeButton && (
<Button variant="warning" size="medium" onClick={handleRevoke} disabled={isActionDisabled}>
{t('sandboxProvider.configModal.revoke', { ns: 'common' })}
</Button>
)}
<Button variant="secondary" size="medium" onClick={onClose} disabled={isActionDisabled}>
{t('sandboxProvider.configModal.cancel', { ns: 'common' })}
</Button>
)}
<Button variant="secondary" size="medium" onClick={onClose} disabled={isActionDisabled}>
{t('sandboxProvider.configModal.cancel', { ns: 'common' })}
</Button>
<Button variant="primary" size="medium" onClick={handleSave} disabled={isActionDisabled}>
{t('sandboxProvider.configModal.save', { ns: 'common' })}
</Button>
<Button variant="primary" size="medium" onClick={handleSave} disabled={isActionDisabled}>
{t('sandboxProvider.configModal.save', { ns: 'common' })}
</Button>
</div>
</div>
</div>
{/* Security tip */}
<div className="-mx-6 -mb-6 mt-4 flex items-start justify-center gap-1 rounded-b-2xl border-t border-divider-subtle bg-background-soft px-2 py-3">
<span className="i-ri-lock-2-fill h-3 w-3 shrink-0 text-text-primary" />
<p className="text-text-tertiary system-xs-regular">
{t('sandboxProvider.configModal.securityTip', { ns: 'common' })}
{' '}
<span className="text-text-accent">PKCS1_OAEP</span>
{' '}
{t('sandboxProvider.configModal.securityTipTechnology', { ns: 'common' })}
</p>
</div>
</Modal>
{/* Security tip */}
<div className="-mx-6 -mb-6 mt-4 flex items-start justify-center gap-1 rounded-b-2xl border-t border-divider-subtle bg-background-soft px-2 py-3">
<span className="i-ri-lock-2-fill h-3 w-3 shrink-0 text-text-primary" />
<p className="text-text-tertiary system-xs-regular">
{t('sandboxProvider.configModal.securityTip', { ns: 'common' })}
{' '}
<span className="text-text-accent">PKCS1_OAEP</span>
{' '}
{t('sandboxProvider.configModal.securityTipTechnology', { ns: 'common' })}
</p>
</div>
</DialogContent>
</Dialog>
)
}

View File

@ -4,8 +4,8 @@ import type { SandboxProvider } from '@/types/sandbox-provider'
import { memo, useCallback } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import Button from '@/app/components/base/button'
import Modal from '@/app/components/base/modal'
import { useToastContext } from '@/app/components/base/toast/context'
import { Dialog, DialogCloseButton, DialogContent, DialogTitle } from '@/app/components/base/ui/dialog'
import { toast } from '@/app/components/base/ui/toast'
import { useActivateSandboxProvider } from '@/service/use-sandbox-provider'
import { PROVIDER_STATIC_LABELS } from './constants'
@ -19,77 +19,75 @@ const SwitchModal = ({
onClose,
}: SwitchModalProps) => {
const { t } = useTranslation()
const { notify } = useToastContext()
const { mutateAsync: activateProvider, isPending } = useActivateSandboxProvider()
const providerLabel = PROVIDER_STATIC_LABELS[provider.provider_type as keyof typeof PROVIDER_STATIC_LABELS]
?? provider.provider_type
// Determine the type based on provider configuration
// If tenant has custom config, activate as 'user', otherwise as 'system'
const activationType: 'system' | 'user' = provider.is_tenant_configured ? 'user' : 'system'
const handleConfirm = useCallback(async () => {
try {
await activateProvider({ providerType: provider.provider_type, type: activationType })
notify({ type: 'success', message: t('api.success', { ns: 'common' }) })
toast.success(t('api.success', { ns: 'common' }))
onClose()
}
catch {
// Error toast is handled by fetch layer
}
}, [activateProvider, provider.provider_type, activationType, notify, t, onClose])
}, [activateProvider, provider.provider_type, activationType, t, onClose])
return (
<Modal
isShow
onClose={onClose}
title={t('sandboxProvider.switchModal.title', { ns: 'common' })}
closable
className="w-[480px]"
>
<div className="mt-4">
{/* Warning Section */}
<div>
<div className="text-text-destructive system-sm-semibold">
{t('sandboxProvider.switchModal.warning', { ns: 'common' })}
<Dialog open onOpenChange={open => !open && onClose()}>
<DialogContent className="w-[480px]">
<DialogCloseButton />
<DialogTitle className="text-text-primary title-2xl-semi-bold">
{t('sandboxProvider.switchModal.title', { ns: 'common' })}
</DialogTitle>
<div className="mt-4">
{/* Warning Section */}
<div>
<div className="text-text-destructive system-sm-semibold">
{t('sandboxProvider.switchModal.warning', { ns: 'common' })}
</div>
<div className="mt-0.5 text-text-destructive system-xs-regular">
{t('sandboxProvider.switchModal.warningDesc', { ns: 'common' })}
</div>
</div>
<div className="mt-0.5 text-text-destructive system-xs-regular">
{t('sandboxProvider.switchModal.warningDesc', { ns: 'common' })}
{/* Confirm Text */}
<div className="mt-4 text-text-secondary system-sm-regular">
<Trans
i18nKey="sandboxProvider.switchModal.confirmText"
ns="common"
values={{ provider: providerLabel }}
components={{ bold: <span className="system-sm-semibold" /> }}
/>
</div>
{/* Footer Actions */}
<div className="mt-6 flex items-center justify-end gap-2">
<Button
variant="secondary"
size="medium"
onClick={onClose}
disabled={isPending}
>
{t('sandboxProvider.switchModal.cancel', { ns: 'common' })}
</Button>
<Button
variant="warning"
size="medium"
onClick={handleConfirm}
disabled={isPending}
>
{t('sandboxProvider.switchModal.confirm', { ns: 'common' })}
</Button>
</div>
</div>
{/* Confirm Text */}
<div className="mt-4 text-text-secondary system-sm-regular">
<Trans
i18nKey="sandboxProvider.switchModal.confirmText"
ns="common"
values={{ provider: providerLabel }}
components={{ bold: <span className="system-sm-semibold" /> }}
/>
</div>
{/* Footer Actions */}
<div className="mt-6 flex items-center justify-end gap-2">
<Button
variant="secondary"
size="medium"
onClick={onClose}
disabled={isPending}
>
{t('sandboxProvider.switchModal.cancel', { ns: 'common' })}
</Button>
<Button
variant="warning"
size="medium"
onClick={handleConfirm}
disabled={isPending}
>
{t('sandboxProvider.switchModal.confirm', { ns: 'common' })}
</Button>
</div>
</div>
</Modal>
</DialogContent>
</Dialog>
)
}