diff --git a/web/app/components/header/account-setting/sandbox-provider-page/config-modal.tsx b/web/app/components/header/account-setting/sandbox-provider-page/config-modal.tsx index a518418eec..b77277517c 100644 --- a/web/app/components/header/account-setting/sandbox-provider-page/config-modal.tsx +++ b/web/app/components/header/account-setting/sandbox-provider-page/config-modal.tsx @@ -12,6 +12,7 @@ import Modal from '@/app/components/base/modal' import RadioUI from '@/app/components/base/radio/ui' import { useToastContext } from '@/app/components/base/toast' import { + useActivateSandboxProvider, useDeleteSandboxProviderConfig, useSaveSandboxProviderConfig, } from '@/service/use-sandbox-provider' @@ -69,6 +70,7 @@ function ConfigModal({ provider, onClose }: ConfigModalProps) { 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) @@ -102,10 +104,10 @@ function ConfigModal({ provider, onClose }: ConfigModalProps) { }, [provider.config_schema, provider.config, t]) const handleSave = useCallback(async () => { - // For managed mode, delete user config to use system defaults + // For managed mode, activate system config (preserves user config for future use) if (shouldShowModeSelection && configMode === 'managed') { try { - await deleteConfig(provider.provider_type) + await activateProvider({ providerType: provider.provider_type, type: 'system' }) notify({ type: 'success', message: t('api.saved', { ns: 'common' }) }) onClose() } @@ -127,6 +129,7 @@ function ConfigModal({ provider, onClose }: ConfigModalProps) { await saveConfig({ providerType: provider.provider_type, config: formValues.values, + activate: true, }) notify({ type: 'success', message: t('api.saved', { ns: 'common' }) }) onClose() @@ -134,7 +137,7 @@ function ConfigModal({ provider, onClose }: ConfigModalProps) { catch { // Error toast is handled by fetch layer } - }, [shouldShowModeSelection, configMode, saveConfig, deleteConfig, provider.provider_type, notify, t, onClose]) + }, [shouldShowModeSelection, configMode, saveConfig, activateProvider, provider.provider_type, notify, t, onClose]) const handleRevoke = useCallback(async () => { try { @@ -154,7 +157,7 @@ function ConfigModal({ provider, onClose }: ConfigModalProps) { // 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 + const isActionDisabled = isSaving || isDeleting || isActivating const showByokForm = !shouldShowModeSelection || configMode === 'byok' return ( diff --git a/web/app/components/header/account-setting/sandbox-provider-page/switch-modal.tsx b/web/app/components/header/account-setting/sandbox-provider-page/switch-modal.tsx index c15049b2e2..a31c6f501d 100644 --- a/web/app/components/header/account-setting/sandbox-provider-page/switch-modal.tsx +++ b/web/app/components/header/account-setting/sandbox-provider-page/switch-modal.tsx @@ -23,16 +23,20 @@ const SwitchModal = ({ const { mutateAsync: activateProvider, isPending } = useActivateSandboxProvider() + // 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(provider.provider_type) + await activateProvider({ providerType: provider.provider_type, type: activationType }) notify({ type: 'success', message: t('api.success', { ns: 'common' }) }) onClose() } catch { // Error toast is handled by fetch layer } - }, [activateProvider, provider.provider_type, notify, t, onClose]) + }, [activateProvider, provider.provider_type, activationType, notify, t, onClose]) return ( + activate?: boolean } }>()) .output(type<{ result: string }>()) @@ -46,5 +47,8 @@ export const activateSandboxProviderContract = base params: { providerType: string } + body: { + type: 'system' | 'user' + } }>()) .output(type<{ result: string }>()) diff --git a/web/service/use-sandbox-provider.ts b/web/service/use-sandbox-provider.ts index 975d3008c6..b038b80ed4 100644 --- a/web/service/use-sandbox-provider.ts +++ b/web/service/use-sandbox-provider.ts @@ -16,10 +16,10 @@ export const useSaveSandboxProviderConfig = () => { const queryClient = useQueryClient() return useMutation({ mutationKey: consoleQuery.sandboxProvider.saveSandboxProviderConfig.mutationKey(), - mutationFn: ({ providerType, config }: { providerType: string, config: Record }) => { + mutationFn: ({ providerType, config, activate }: { providerType: string, config: Record, activate?: boolean }) => { return consoleClient.sandboxProvider.saveSandboxProviderConfig({ params: { providerType }, - body: { config }, + body: { config, activate }, }) }, onSuccess: () => { @@ -47,9 +47,10 @@ export const useActivateSandboxProvider = () => { const queryClient = useQueryClient() return useMutation({ mutationKey: consoleQuery.sandboxProvider.activateSandboxProvider.mutationKey(), - mutationFn: (providerType: string) => { + mutationFn: ({ providerType, type }: { providerType: string, type: 'system' | 'user' }) => { return consoleClient.sandboxProvider.activateSandboxProvider({ params: { providerType }, + body: { type }, }) }, onSuccess: () => {