Merge branch 'feat/plugins' into dev/plugin-deploy

This commit is contained in:
zxhlyh 2024-12-10 14:58:38 +08:00
commit 3803989480
8 changed files with 58 additions and 50 deletions

View File

@ -8,7 +8,7 @@ const PluginList = async () => {
return ( return (
<PluginPage <PluginPage
plugins={<PluginsPanel />} plugins={<PluginsPanel />}
marketplace={<Marketplace locale={locale} shouldExclude pluginTypeSwitchClassName='top-[60px]' />} marketplace={<Marketplace locale={locale} pluginTypeSwitchClassName='top-[60px]' />}
/> />
) )
} }

View File

@ -72,6 +72,7 @@ import { SupportUploadFileTypes } from '@/app/components/workflow/types'
import NewFeaturePanel from '@/app/components/base/features/new-feature-panel' import NewFeaturePanel from '@/app/components/base/features/new-feature-panel'
import { fetchFileUploadConfig } from '@/service/common' import { fetchFileUploadConfig } from '@/service/common'
import { correctProvider } from '@/utils' import { correctProvider } from '@/utils'
import PluginDependency from '@/app/components/workflow/plugin-dependency'
type PublishConfig = { type PublishConfig = {
modelConfig: ModelConfig modelConfig: ModelConfig
@ -1041,6 +1042,7 @@ const Configuration: FC = () => {
onAutoAddPromptVariable={handleAddPromptVariable} onAutoAddPromptVariable={handleAddPromptVariable}
/> />
)} )}
<PluginDependency />
</> </>
</FeaturesProvider> </FeaturesProvider>
</ConfigContext.Provider> </ConfigContext.Provider>

View File

@ -25,8 +25,7 @@ import AppsFull from '@/app/components/billing/apps-full-in-dialog'
import { NEED_REFRESH_APP_LIST_KEY } from '@/config' import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
import { getRedirection } from '@/utils/app-redirection' import { getRedirection } from '@/utils/app-redirection'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { useStore as usePluginDependencyStore } from '@/app/components/workflow/plugin-dependency/store' import { usePluginDependencies } from '@/app/components/workflow/plugin-dependency/hooks'
import PluginDependency from '@/app/components/workflow/plugin-dependency'
type CreateFromDSLModalProps = { type CreateFromDSLModalProps = {
show: boolean show: boolean
@ -52,6 +51,7 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS
const [showErrorModal, setShowErrorModal] = useState(false) const [showErrorModal, setShowErrorModal] = useState(false)
const [versions, setVersions] = useState<{ importedVersion: string; systemVersion: string }>() const [versions, setVersions] = useState<{ importedVersion: string; systemVersion: string }>()
const [importId, setImportId] = useState<string>() const [importId, setImportId] = useState<string>()
const { handleCheckPluginDependencies } = usePluginDependencies()
const readFile = (file: File) => { const readFile = (file: File) => {
const reader = new FileReader() const reader = new FileReader()
@ -103,11 +103,7 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS
if (!response) if (!response)
return return
const { id, status, app_id, imported_dsl_version, current_dsl_version, leaked_dependencies } = response const { id, status, app_id, imported_dsl_version, current_dsl_version } = response
if (leaked_dependencies?.length) {
const { setDependencies } = usePluginDependencyStore.getState()
setDependencies(leaked_dependencies)
}
if (status === DSLImportStatus.COMPLETED || status === DSLImportStatus.COMPLETED_WITH_WARNINGS) { if (status === DSLImportStatus.COMPLETED || status === DSLImportStatus.COMPLETED_WITH_WARNINGS) {
if (onSuccess) if (onSuccess)
onSuccess() onSuccess()
@ -120,6 +116,8 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS
children: status === DSLImportStatus.COMPLETED_WITH_WARNINGS && t('app.newApp.appCreateDSLWarning'), children: status === DSLImportStatus.COMPLETED_WITH_WARNINGS && t('app.newApp.appCreateDSLWarning'),
}) })
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1') localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
if (app_id)
await handleCheckPluginDependencies(app_id)
getRedirection(isCurrentWorkspaceEditor, { id: app_id }, push) getRedirection(isCurrentWorkspaceEditor, { id: app_id }, push)
} }
else if (status === DSLImportStatus.PENDING) { else if (status === DSLImportStatus.PENDING) {
@ -138,6 +136,7 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS
notify({ type: 'error', message: t('app.newApp.appCreateFailed') }) notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
} }
} }
// eslint-disable-next-line unused-imports/no-unused-vars
catch (e) { catch (e) {
notify({ type: 'error', message: t('app.newApp.appCreateFailed') }) notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
} }
@ -164,6 +163,8 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS
type: 'success', type: 'success',
message: t('app.newApp.appCreated'), message: t('app.newApp.appCreated'),
}) })
if (app_id)
await handleCheckPluginDependencies(app_id)
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1') localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
getRedirection(isCurrentWorkspaceEditor, { id: app_id }, push) getRedirection(isCurrentWorkspaceEditor, { id: app_id }, push)
} }
@ -171,6 +172,7 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS
notify({ type: 'error', message: t('app.newApp.appCreateFailed') }) notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
} }
} }
// eslint-disable-next-line unused-imports/no-unused-vars
catch (e) { catch (e) {
notify({ type: 'error', message: t('app.newApp.appCreateFailed') }) notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
} }
@ -282,7 +284,6 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS
<div>{t('app.newApp.appCreateDSLErrorPart4')}<span className='system-md-medium'>{versions?.systemVersion}</span></div> <div>{t('app.newApp.appCreateDSLErrorPart4')}<span className='system-md-medium'>{versions?.systemVersion}</span></div>
</div> </div>
</div> </div>
<PluginDependency />
<div className='flex pt-6 justify-end items-start gap-2 self-stretch'> <div className='flex pt-6 justify-end items-start gap-2 self-stretch'>
<Button variant='secondary' onClick={() => setShowErrorModal(false)}>{t('app.newApp.Cancel')}</Button> <Button variant='secondary' onClick={() => setShowErrorModal(false)}>{t('app.newApp.Cancel')}</Button>
<Button variant='primary' destructive onClick={onDSLConfirm}>{t('app.newApp.Confirm')}</Button> <Button variant='primary' destructive onClick={onDSLConfirm}>{t('app.newApp.Confirm')}</Button>

View File

@ -72,6 +72,7 @@ import SyncingDataModal from './syncing-data-modal'
import UpdateDSLModal from './update-dsl-modal' import UpdateDSLModal from './update-dsl-modal'
import DSLExportConfirmModal from './dsl-export-confirm-modal' import DSLExportConfirmModal from './dsl-export-confirm-modal'
import LimitTips from './limit-tips' import LimitTips from './limit-tips'
import PluginDependency from './plugin-dependency'
import { import {
useStore, useStore,
useWorkflowStore, useWorkflowStore,
@ -327,6 +328,7 @@ const Workflow: FC<WorkflowProps> = memo(({
) )
} }
<LimitTips /> <LimitTips />
<PluginDependency />
<ReactFlow <ReactFlow
nodeTypes={nodeTypes} nodeTypes={nodeTypes}
edgeTypes={edgeTypes} edgeTypes={edgeTypes}

View File

@ -0,0 +1,17 @@
import { useCallback } from 'react'
import { useStore as usePluginDependenciesStore } from './store'
import { useMutationCheckDependecies } from '@/service/use-plugins'
export const usePluginDependencies = () => {
const { mutateAsync } = useMutationCheckDependecies()
const handleCheckPluginDependencies = useCallback(async (appId: string) => {
const { leaked_dependencies } = await mutateAsync(appId)
const { setDependencies } = usePluginDependenciesStore.getState()
setDependencies(leaked_dependencies)
}, [mutateAsync])
return {
handleCheckPluginDependencies,
}
}

View File

@ -1,45 +1,23 @@
import { import { useCallback } from 'react'
useCallback,
useState,
} from 'react'
import { useTranslation } from 'react-i18next'
import { useStore } from './store' import { useStore } from './store'
import ReadyToInstall from '@/app/components/plugins/install-plugin/install-bundle/ready-to-install' import InstallBundle from '@/app/components/plugins/install-plugin/install-bundle'
import { InstallStep } from '@/app/components/plugins/types'
const i18nPrefix = 'plugin.installModal'
const PluginDependency = () => { const PluginDependency = () => {
const dependencies = useStore(s => s.dependencies) const dependencies = useStore(s => s.dependencies)
const [step, setStep] = useState<InstallStep>(InstallStep.readyToInstall) const handleCancelInstallBundle = useCallback(() => {
const { setDependencies } = useStore.getState()
const { t } = useTranslation() setDependencies([])
const getTitle = useCallback(() => { }, [])
if (step === InstallStep.uploadFailed)
return t(`${i18nPrefix}.uploadFailed`)
if (step === InstallStep.installed)
return t(`${i18nPrefix}.installComplete`)
return t(`${i18nPrefix}.installPlugin`)
}, [step, t])
if (!dependencies.length) if (!dependencies.length)
return null return null
return ( return (
<div> <InstallBundle
<div className='flex pt-6 pl-6 pb-3 pr-14 items-start gap-2 self-stretch'> fromDSLPayload={dependencies}
<div className='self-stretch text-text-primary title-2xl-semi-bold'> onClose={handleCancelInstallBundle}
{getTitle()} />
</div>
</div>
<ReadyToInstall
step={step}
onStepChange={setStep}
allPlugins={dependencies}
onClose={() => {}}
/>
</div>
) )
} }

View File

@ -38,8 +38,7 @@ import { ToastContext } from '@/app/components/base/toast'
import { useEventEmitterContextContext } from '@/context/event-emitter' import { useEventEmitterContextContext } from '@/context/event-emitter'
import { useStore as useAppStore } from '@/app/components/app/store' import { useStore as useAppStore } from '@/app/components/app/store'
import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants' import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants'
import PluginDependency from '@/app/components/workflow/plugin-dependency' import { usePluginDependencies } from '@/app/components/workflow/plugin-dependency/hooks'
import { useStore as usePluginDependencyStore } from '@/app/components/workflow/plugin-dependency/store'
type UpdateDSLModalProps = { type UpdateDSLModalProps = {
onCancel: () => void onCancel: () => void
@ -63,6 +62,7 @@ const UpdateDSLModal = ({
const [showErrorModal, setShowErrorModal] = useState(false) const [showErrorModal, setShowErrorModal] = useState(false)
const [versions, setVersions] = useState<{ importedVersion: string; systemVersion: string }>() const [versions, setVersions] = useState<{ importedVersion: string; systemVersion: string }>()
const [importId, setImportId] = useState<string>() const [importId, setImportId] = useState<string>()
const { handleCheckPluginDependencies } = usePluginDependencies()
const readFile = (file: File) => { const readFile = (file: File) => {
const reader = new FileReader() const reader = new FileReader()
@ -137,11 +137,8 @@ const UpdateDSLModal = ({
if (appDetail && fileContent) { if (appDetail && fileContent) {
setLoading(true) setLoading(true)
const response = await importDSL({ mode: DSLImportMode.YAML_CONTENT, yaml_content: fileContent, app_id: appDetail.id }) const response = await importDSL({ mode: DSLImportMode.YAML_CONTENT, yaml_content: fileContent, app_id: appDetail.id })
const { id, status, app_id, imported_dsl_version, current_dsl_version, leaked_dependencies } = response const { id, status, app_id, imported_dsl_version, current_dsl_version } = response
if (leaked_dependencies?.length) {
const { setDependencies } = usePluginDependencyStore.getState()
setDependencies(leaked_dependencies)
}
if (status === DSLImportStatus.COMPLETED || status === DSLImportStatus.COMPLETED_WITH_WARNINGS) { if (status === DSLImportStatus.COMPLETED || status === DSLImportStatus.COMPLETED_WITH_WARNINGS) {
if (!app_id) { if (!app_id) {
notify({ type: 'error', message: t('workflow.common.importFailure') }) notify({ type: 'error', message: t('workflow.common.importFailure') })
@ -155,6 +152,7 @@ const UpdateDSLModal = ({
message: t(status === DSLImportStatus.COMPLETED ? 'workflow.common.importSuccess' : 'workflow.common.importWarning'), message: t(status === DSLImportStatus.COMPLETED ? 'workflow.common.importSuccess' : 'workflow.common.importWarning'),
children: status === DSLImportStatus.COMPLETED_WITH_WARNINGS && t('workflow.common.importWarningDetails'), children: status === DSLImportStatus.COMPLETED_WITH_WARNINGS && t('workflow.common.importWarningDetails'),
}) })
await handleCheckPluginDependencies(app_id)
setLoading(false) setLoading(false)
onCancel() onCancel()
} }
@ -175,12 +173,13 @@ const UpdateDSLModal = ({
} }
} }
} }
// eslint-disable-next-line unused-imports/no-unused-vars
catch (e) { catch (e) {
setLoading(false) setLoading(false)
notify({ type: 'error', message: t('workflow.common.importFailure') }) notify({ type: 'error', message: t('workflow.common.importFailure') })
} }
isCreatingRef.current = false isCreatingRef.current = false
}, [currentFile, fileContent, onCancel, notify, t, appDetail, onImport, handleWorkflowUpdate]) }, [currentFile, fileContent, onCancel, notify, t, appDetail, onImport, handleWorkflowUpdate, handleCheckPluginDependencies])
const onUpdateDSLConfirm: MouseEventHandler = async () => { const onUpdateDSLConfirm: MouseEventHandler = async () => {
try { try {
@ -198,6 +197,7 @@ const UpdateDSLModal = ({
return return
} }
handleWorkflowUpdate(app_id) handleWorkflowUpdate(app_id)
await handleCheckPluginDependencies(app_id)
if (onImport) if (onImport)
onImport() onImport()
notify({ type: 'success', message: t('workflow.common.importSuccess') }) notify({ type: 'success', message: t('workflow.common.importSuccess') })
@ -209,6 +209,7 @@ const UpdateDSLModal = ({
notify({ type: 'error', message: t('workflow.common.importFailure') }) notify({ type: 'error', message: t('workflow.common.importFailure') })
} }
} }
// eslint-disable-next-line unused-imports/no-unused-vars
catch (e) { catch (e) {
setLoading(false) setLoading(false)
notify({ type: 'error', message: t('workflow.common.importFailure') }) notify({ type: 'error', message: t('workflow.common.importFailure') })
@ -289,7 +290,6 @@ const UpdateDSLModal = ({
<div>{t('app.newApp.appCreateDSLErrorPart4')}<span className='system-md-medium'>{versions?.systemVersion}</span></div> <div>{t('app.newApp.appCreateDSLErrorPart4')}<span className='system-md-medium'>{versions?.systemVersion}</span></div>
</div> </div>
</div> </div>
<PluginDependency />
<div className='flex pt-6 justify-end items-start gap-2 self-stretch'> <div className='flex pt-6 justify-end items-start gap-2 self-stretch'>
<Button variant='secondary' onClick={() => setShowErrorModal(false)}>{t('app.newApp.Cancel')}</Button> <Button variant='secondary' onClick={() => setShowErrorModal(false)}>{t('app.newApp.Cancel')}</Button>
<Button variant='primary' destructive onClick={onUpdateDSLConfirm}>{t('app.newApp.Confirm')}</Button> <Button variant='primary' destructive onClick={onUpdateDSLConfirm}>{t('app.newApp.Confirm')}</Button>

View File

@ -407,3 +407,11 @@ export const useDownloadPlugin = (info: { organization: string; pluginName: stri
retry: 0, retry: 0,
}) })
} }
export const useMutationCheckDependecies = () => {
return useMutation({
mutationFn: (appId: string) => {
return get<{ leaked_dependencies: Dependency[] }>(`/apps/import/${appId}/check-dependencies`)
},
})
}