feat: plugin auto upgrade strategy (#19758)

Co-authored-by: Joel <iamjoel007@gmail.com>
Co-authored-by: crazywoola <427733928@qq.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Novice <novice12185727@gmail.com>
This commit is contained in:
Junyan Qin (Chin)
2025-07-23 15:33:39 +08:00
committed by GitHub
parent e6913744ae
commit eaae79a581
305 changed files with 2524 additions and 581 deletions

View File

@@ -40,6 +40,11 @@ import { PluginAuth } from '@/app/components/plugins/plugin-auth'
import { AuthCategory } from '@/app/components/plugins/plugin-auth'
import { useAllToolProviders } from '@/service/use-tools'
import DeprecationNotice from '../base/deprecation-notice'
import { AutoUpdateLine } from '../../base/icons/src/vender/system'
import { convertUTCDaySecondsToLocalSeconds, timeOfDayToDayjs } from '../reference-setting-modal/auto-update-setting/utils'
import useReferenceSetting from '../plugin-page/use-reference-setting'
import { AUTO_UPDATE_MODE } from '../reference-setting-modal/auto-update-setting/types'
import { useAppContext } from '@/context/app-context'
const i18nPrefix = 'plugin.action'
@@ -55,6 +60,8 @@ const DetailHeader = ({
onUpdate,
}: Props) => {
const { t } = useTranslation()
const { userProfile: { timezone } } = useAppContext()
const { theme } = useTheme()
const locale = useGetLanguage()
const { locale: currentLocale } = useI18N()
@@ -112,8 +119,24 @@ const DetailHeader = ({
setFalse: hideUpdateModal,
}] = useBoolean(false)
const handleUpdate = async () => {
const { referenceSetting } = useReferenceSetting()
const { auto_upgrade: autoUpgradeInfo } = referenceSetting || {}
const isAutoUpgradeEnabled = useMemo(() => {
if (!autoUpgradeInfo || !isFromMarketplace)
return false
if(autoUpgradeInfo.upgrade_mode === AUTO_UPDATE_MODE.update_all)
return true
if(autoUpgradeInfo.upgrade_mode === AUTO_UPDATE_MODE.partial && autoUpgradeInfo.include_plugins.includes(plugin_id))
return true
if(autoUpgradeInfo.upgrade_mode === AUTO_UPDATE_MODE.exclude && !autoUpgradeInfo.exclude_plugins.includes(plugin_id))
return true
return false
}, [autoUpgradeInfo, plugin_id, isFromMarketplace])
const [isDowngrade, setIsDowngrade] = useState(false)
const handleUpdate = async (isDowngrade?: boolean) => {
if (isFromMarketplace) {
setIsDowngrade(!!isDowngrade)
showUpdateModal()
return
}
@@ -180,9 +203,6 @@ const DetailHeader = ({
}
}, [showDeleting, installation_id, hideDeleting, hideDeleteConfirm, onUpdate, category, refreshModelProviders, invalidateAllToolProviders])
// #plugin TODO# used in apps
// const usedInApps = 3
return (
<div className={cn('shrink-0 border-b border-divider-subtle bg-components-panel-bg p-4 pb-3')}>
<div className="flex">
@@ -201,7 +221,7 @@ const DetailHeader = ({
currentVersion={version}
onSelect={(state) => {
setTargetVersion(state)
handleUpdate()
handleUpdate(state.isDowngrade)
}}
trigger={
<Badge
@@ -221,6 +241,18 @@ const DetailHeader = ({
/>
}
/>
{/* Auto update info */}
{isAutoUpgradeEnabled && (
<Tooltip popupContent={t('plugin.autoUpdate.nextUpdateTime', { time: timeOfDayToDayjs(convertUTCDaySecondsToLocalSeconds(autoUpgradeInfo?.upgrade_time_of_day || 0, timezone!)).format('hh:mm A') })}>
{/* add a a div to fix tooltip hover not show problem */}
<div>
<Badge className='mr-1 cursor-pointer px-1'>
<AutoUpdateLine className='size-3' />
</Badge>
</div>
</Tooltip>
)}
{(hasNewVersion || isFromGitHub) && (
<Button variant='secondary-accent' size='small' className='!h-5' onClick={() => {
if (isFromMarketplace) {
@@ -324,6 +356,7 @@ const DetailHeader = ({
{
isShowUpdateModal && (
<UpdateFromMarketplace
pluginId={plugin_id}
payload={{
category: detail.declaration.category,
originalPackageInfo: {
@@ -337,6 +370,7 @@ const DetailHeader = ({
}}
onCancel={hideUpdateModal}
onSave={handleUpdatedFromMarketplace}
isShowDowngradeWarningModal={isDowngrade && isAutoUpgradeEnabled}
/>
)
}