mirror of https://github.com/langgenius/dify.git
feat: support install bundle from marketplace
This commit is contained in:
parent
b93be49530
commit
df049564e8
|
|
@ -22,8 +22,10 @@ const InstallByDSLList: FC<Props> = ({
|
|||
onSelect,
|
||||
onLoadedAllPlugin,
|
||||
}) => {
|
||||
const { isLoading: isFetchingMarketplaceDataFromDSL, data: marketplaceFromDSLRes } = useFetchPluginsInMarketPlaceByIds(allPlugins.filter(d => d.type === 'marketplace').map(d => (d as GitHubItemAndMarketPlaceDependency).value.plugin_unique_identifier!))
|
||||
const { isLoading: isFetchingMarketplaceDataFromLocal, data: marketplaceResFromLocalRes } = useFetchPluginsInMarketPlaceByInfo(allPlugins.filter(d => d.type === 'marketplace').map(d => (d as GitHubItemAndMarketPlaceDependency).value!))
|
||||
// DSL has id, to get plugin info to show more info
|
||||
const { isLoading: isFetchingMarketplaceDataById, data: infoGetById, error: infoByIdError } = useFetchPluginsInMarketPlaceByIds(allPlugins.filter(d => d.type === 'marketplace').map(d => (d as GitHubItemAndMarketPlaceDependency).value.plugin_unique_identifier!))
|
||||
// has meta(org,name,version), to get id
|
||||
const { isLoading: isFetchingDataByMeta, data: infoByMeta, error: infoByMetaError } = useFetchPluginsInMarketPlaceByInfo(allPlugins.filter(d => d.type === 'marketplace').map(d => (d as GitHubItemAndMarketPlaceDependency).value!))
|
||||
const [plugins, doSetPlugins] = useState<(Plugin | undefined)[]>((() => {
|
||||
const hasLocalPackage = allPlugins.some(d => d.type === 'package')
|
||||
if (!hasLocalPackage)
|
||||
|
|
@ -75,8 +77,8 @@ const InstallByDSLList: FC<Props> = ({
|
|||
}, [allPlugins])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isFetchingMarketplaceDataFromDSL && marketplaceFromDSLRes?.data.plugins) {
|
||||
const payloads = marketplaceFromDSLRes?.data.plugins
|
||||
if (!isFetchingMarketplaceDataById && infoGetById?.data.plugins) {
|
||||
const payloads = infoGetById?.data.plugins
|
||||
const failedIndex: number[] = []
|
||||
const nextPlugins = produce(pluginsRef.current, (draft) => {
|
||||
marketPlaceInDSLIndex.forEach((index, i) => {
|
||||
|
|
@ -92,11 +94,11 @@ const InstallByDSLList: FC<Props> = ({
|
|||
setErrorIndexes([...errorIndexes, ...failedIndex])
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isFetchingMarketplaceDataFromDSL])
|
||||
}, [isFetchingMarketplaceDataById])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isFetchingMarketplaceDataFromLocal && marketplaceResFromLocalRes?.data.list) {
|
||||
const payloads = marketplaceResFromLocalRes?.data.list
|
||||
if (!isFetchingDataByMeta && infoByMeta?.data.list) {
|
||||
const payloads = infoByMeta?.data.list
|
||||
const failedIndex: number[] = []
|
||||
const nextPlugins = produce(pluginsRef.current, (draft) => {
|
||||
marketPlaceInDSLIndex.forEach((index, i) => {
|
||||
|
|
@ -117,7 +119,15 @@ const InstallByDSLList: FC<Props> = ({
|
|||
setErrorIndexes([...errorIndexes, ...failedIndex])
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isFetchingMarketplaceDataFromLocal])
|
||||
}, [isFetchingDataByMeta])
|
||||
|
||||
useEffect(() => {
|
||||
// get info all failed
|
||||
if (infoByMetaError || infoByIdError)
|
||||
setErrorIndexes([...errorIndexes, ...marketPlaceInDSLIndex])
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [infoByMetaError, infoByIdError])
|
||||
|
||||
const isLoadedAllData = (plugins.filter(p => !!p).length + errorIndexes.length) === allPlugins.length
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ const InstallFromMarketplace: React.FC<InstallFromMarketplaceProps> = ({
|
|||
updateModelProviders()
|
||||
if (PluginType.tool.includes(manifest.category))
|
||||
invalidateAllToolProviders()
|
||||
}, [invalidateAllToolProviders, invalidateInstalledPluginList, manifest.category, updateModelProviders])
|
||||
}, [invalidateAllToolProviders, invalidateInstalledPluginList, manifest, updateModelProviders])
|
||||
|
||||
const handleFailed = useCallback((errorMsg?: string) => {
|
||||
setStep(InstallStep.installFailed)
|
||||
|
|
@ -76,17 +76,6 @@ const InstallFromMarketplace: React.FC<InstallFromMarketplaceProps> = ({
|
|||
{getTitle()}
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
step === InstallStep.readyToInstall && (
|
||||
<Install
|
||||
uniqueIdentifier={uniqueIdentifier}
|
||||
payload={manifest!}
|
||||
onCancel={onClose}
|
||||
onInstalled={handleInstalled}
|
||||
onFailed={handleFailed}
|
||||
/>
|
||||
)
|
||||
}
|
||||
{
|
||||
isBundle ? (
|
||||
<ReadyToInstallBundle
|
||||
|
|
@ -95,17 +84,32 @@ const InstallFromMarketplace: React.FC<InstallFromMarketplaceProps> = ({
|
|||
onClose={onClose}
|
||||
allPlugins={dependencies!}
|
||||
/>
|
||||
) : ([InstallStep.installed, InstallStep.installFailed].includes(step)) && (
|
||||
<Installed
|
||||
payload={manifest!}
|
||||
isMarketPayload
|
||||
isFailed={step === InstallStep.installFailed}
|
||||
errMsg={errorMsg}
|
||||
onCancel={onSuccess}
|
||||
/>
|
||||
) : (<>
|
||||
{
|
||||
step === InstallStep.readyToInstall && (
|
||||
<Install
|
||||
uniqueIdentifier={uniqueIdentifier}
|
||||
payload={manifest!}
|
||||
onCancel={onClose}
|
||||
onInstalled={handleInstalled}
|
||||
onFailed={handleFailed}
|
||||
/>
|
||||
)}
|
||||
{
|
||||
[InstallStep.installed, InstallStep.installFailed].includes(step) && (
|
||||
<Installed
|
||||
payload={manifest!}
|
||||
isMarketPayload
|
||||
isFailed={step === InstallStep.installFailed}
|
||||
errMsg={errorMsg}
|
||||
onCancel={onSuccess}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
</Modal>
|
||||
</Modal >
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ const Installed: FC<Props> = ({
|
|||
</>
|
||||
)
|
||||
}</>)
|
||||
}, [payload.latest_version, supportCheckInstalled])
|
||||
}, [payload.latest_version, payload.version, supportCheckInstalled])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -28,13 +28,15 @@ import {
|
|||
useRouter,
|
||||
useSearchParams,
|
||||
} from 'next/navigation'
|
||||
import type { Dependency } from '../types'
|
||||
import type { PluginDeclaration, PluginManifestInMarket } from '../types'
|
||||
import { sleep } from '@/utils'
|
||||
import { fetchManifestFromMarketPlace } from '@/service/plugins'
|
||||
import { fetchBundleInfoFromMarketPlace, fetchManifestFromMarketPlace } from '@/service/plugins'
|
||||
import { marketplaceApiPrefix } from '@/config'
|
||||
import { SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS } from '@/config'
|
||||
|
||||
const PACKAGE_IDS_KEY = 'package-ids'
|
||||
const BUNDLE_INFO_KEY = 'bundle-info'
|
||||
|
||||
export type PluginPageProps = {
|
||||
plugins: React.ReactNode
|
||||
|
|
@ -58,6 +60,18 @@ const PluginPage = ({
|
|||
return ''
|
||||
}
|
||||
}, [searchParams])
|
||||
|
||||
const [dependencies, setDependencies] = useState<Dependency[]>([])
|
||||
const bundleInfo = useMemo(() => {
|
||||
const info = searchParams.get(BUNDLE_INFO_KEY)
|
||||
try {
|
||||
return info ? JSON.parse(info) : undefined
|
||||
}
|
||||
catch (e) {
|
||||
return undefined
|
||||
}
|
||||
}, [searchParams])
|
||||
|
||||
const [isShowInstallFromMarketplace, {
|
||||
setTrue: showInstallFromMarketplace,
|
||||
setFalse: doHideInstallFromMarketplace,
|
||||
|
|
@ -67,6 +81,7 @@ const PluginPage = ({
|
|||
doHideInstallFromMarketplace()
|
||||
const url = new URL(window.location.href)
|
||||
url.searchParams.delete(PACKAGE_IDS_KEY)
|
||||
url.searchParams.delete(BUNDLE_INFO_KEY)
|
||||
replace(url.toString())
|
||||
}
|
||||
const [manifest, setManifest] = useState<PluginDeclaration | PluginManifestInMarket | null>(null)
|
||||
|
|
@ -83,10 +98,16 @@ const PluginPage = ({
|
|||
icon: `${marketplaceApiPrefix}/plugins/${plugin.org}/${plugin.name}/icon`,
|
||||
})
|
||||
showInstallFromMarketplace()
|
||||
return
|
||||
}
|
||||
if (bundleInfo) {
|
||||
const { data } = await fetchBundleInfoFromMarketPlace(bundleInfo)
|
||||
setDependencies(data.version.dependencies)
|
||||
showInstallFromMarketplace()
|
||||
}
|
||||
})()
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [packageId])
|
||||
}, [packageId, bundleInfo])
|
||||
|
||||
const {
|
||||
canManagement,
|
||||
|
|
@ -211,6 +232,8 @@ const PluginPage = ({
|
|||
<InstallFromMarketplace
|
||||
manifest={manifest! as PluginManifestInMarket}
|
||||
uniqueIdentifier={packageId}
|
||||
isBundle={!!bundleInfo}
|
||||
dependencies={dependencies}
|
||||
onClose={hideInstallFromMarketplace}
|
||||
onSuccess={hideInstallFromMarketplace}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import type { Fetcher } from 'swr'
|
||||
import { get, getMarketplace, post, upload } from './base'
|
||||
import type {
|
||||
Dependency,
|
||||
InstallPackageResponse,
|
||||
Permissions,
|
||||
PluginDeclaration,
|
||||
|
|
@ -66,6 +67,14 @@ export const fetchManifestFromMarketPlace = async (uniqueIdentifier: string) =>
|
|||
return getMarketplace<{ data: { plugin: PluginManifestInMarket, version: { version: string } } }>(`/plugins/identifier?unique_identifier=${uniqueIdentifier}`)
|
||||
}
|
||||
|
||||
export const fetchBundleInfoFromMarketPlace = async ({
|
||||
org,
|
||||
name,
|
||||
version,
|
||||
}: Record<string, string>) => {
|
||||
return getMarketplace<{ data: { version: { dependencies: Dependency[] } } }>(`/bundles/${org}/${name}/${version}`)
|
||||
}
|
||||
|
||||
export const fetchMarketplaceCollections: Fetcher<MarketplaceCollectionsResponse, { url: string; }> = ({ url }) => {
|
||||
return get<MarketplaceCollectionsResponse>(url)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ export const useUploadGitHub = (payload: {
|
|||
queryFn: () => post<uploadGitHubResponse>('/workspaces/current/plugin/upload/github', {
|
||||
body: payload,
|
||||
}),
|
||||
retry: 0,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue