mirror of
https://github.com/langgenius/dify.git
synced 2025-12-29 02:27:24 +00:00
Compare commits
17 Commits
fix/agent-
...
fix/handle
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a01fb08c0 | ||
|
|
3c868a9701 | ||
|
|
e5987a4672 | ||
|
|
4bd039ac1f | ||
|
|
1c269a32b8 | ||
|
|
b8b7805d81 | ||
|
|
0c62e000cd | ||
|
|
316c418a01 | ||
|
|
4886e5ae96 | ||
|
|
7f4a8b955d | ||
|
|
83d0142641 | ||
|
|
3ff07b8e4d | ||
|
|
56c7f49625 | ||
|
|
7c1d842cfe | ||
|
|
2ea3b64a45 | ||
|
|
824f8d8994 | ||
|
|
31c17e6378 |
@@ -14,6 +14,7 @@ from controllers.console.wraps import account_initialization_required, enterpris
|
||||
from core.errors.error import LLMBadRequestError, ProviderTokenNotInitError
|
||||
from core.indexing_runner import IndexingRunner
|
||||
from core.model_runtime.entities.model_entities import ModelType
|
||||
from core.plugin.entities.plugin import ModelProviderID
|
||||
from core.provider_manager import ProviderManager
|
||||
from core.rag.datasource.vdb.vector_type import VectorType
|
||||
from core.rag.extractor.entity.extract_setting import ExtractSetting
|
||||
@@ -72,7 +73,9 @@ class DatasetListApi(Resource):
|
||||
|
||||
data = marshal(datasets, dataset_detail_fields)
|
||||
for item in data:
|
||||
# convert embedding_model_provider to plugin standard format
|
||||
if item["indexing_technique"] == "high_quality":
|
||||
item["embedding_model_provider"] = str(ModelProviderID(item["embedding_model_provider"]))
|
||||
item_model = f"{item['embedding_model']}:{item['embedding_model_provider']}"
|
||||
if item_model in model_names:
|
||||
item["embedding_available"] = True
|
||||
|
||||
@@ -20,6 +20,7 @@ from core.model_runtime.model_providers.__base.text_embedding_model import TextE
|
||||
from core.model_runtime.model_providers.__base.tts_model import TTSModel
|
||||
from core.model_runtime.schema_validators.model_credential_schema_validator import ModelCredentialSchemaValidator
|
||||
from core.model_runtime.schema_validators.provider_credential_schema_validator import ProviderCredentialSchemaValidator
|
||||
from core.plugin.entities.plugin import ModelProviderID
|
||||
from core.plugin.entities.plugin_daemon import PluginModelProviderEntity
|
||||
from core.plugin.manager.asset import PluginAssetManager
|
||||
from core.plugin.manager.model import PluginModelManager
|
||||
@@ -112,6 +113,9 @@ class ModelProviderFactory:
|
||||
:param provider: provider name
|
||||
:return: provider schema
|
||||
"""
|
||||
if "/" not in provider:
|
||||
provider = str(ModelProviderID(provider))
|
||||
|
||||
# fetch plugin model providers
|
||||
plugin_model_provider_entities = self.get_plugin_model_providers()
|
||||
|
||||
@@ -363,4 +367,4 @@ class ModelProviderFactory:
|
||||
plugin_id = "/".join(provider.split("/")[:-1])
|
||||
provider_name = provider.split("/")[-1]
|
||||
|
||||
return plugin_id, provider_name
|
||||
return str(plugin_id), provider_name
|
||||
|
||||
@@ -169,6 +169,21 @@ class GenericProviderID:
|
||||
return f"{self.organization}/{self.plugin_name}"
|
||||
|
||||
|
||||
class ModelProviderID(GenericProviderID):
|
||||
def __init__(self, value: str, is_hardcoded: bool = False) -> None:
|
||||
super().__init__(value, is_hardcoded)
|
||||
if self.organization == "langgenius" and self.provider_name == "google":
|
||||
self.plugin_name = "gemini"
|
||||
|
||||
|
||||
class ToolProviderID(GenericProviderID):
|
||||
def __init__(self, value: str, is_hardcoded: bool = False) -> None:
|
||||
super().__init__(value, is_hardcoded)
|
||||
if self.organization == "langgenius":
|
||||
if self.provider_name in ["jina", "siliconflow"]:
|
||||
self.plugin_name = f"{self.provider_name}_tool"
|
||||
|
||||
|
||||
class PluginDependency(BaseModel):
|
||||
class Type(enum.StrEnum):
|
||||
Github = PluginInstallationSource.Github.value
|
||||
|
||||
@@ -30,6 +30,7 @@ from core.model_runtime.entities.provider_entities import (
|
||||
ProviderEntity,
|
||||
)
|
||||
from core.model_runtime.model_providers.model_provider_factory import ModelProviderFactory
|
||||
from core.plugin.entities.plugin import ModelProviderID
|
||||
from extensions import ext_hosting_provider
|
||||
from extensions.ext_database import db
|
||||
from extensions.ext_redis import redis_client
|
||||
@@ -191,7 +192,7 @@ class ProviderManager:
|
||||
model_settings=model_settings,
|
||||
)
|
||||
|
||||
provider_configurations[provider_name] = provider_configuration
|
||||
provider_configurations[str(ModelProviderID(provider_name))] = provider_configuration
|
||||
|
||||
# Return the encapsulated object
|
||||
return provider_configurations
|
||||
|
||||
@@ -164,7 +164,8 @@ class AgentNode(ToolNode):
|
||||
params = {}
|
||||
for key, param in parameters.items():
|
||||
if param.get("auto", ParamsAutoGenerated.OPEN.value) == ParamsAutoGenerated.CLOSE.value:
|
||||
params[key] = param.get("value", {}).get("value", "")
|
||||
value_param = param.get("value", {})
|
||||
params[key] = value_param.get("value", "") if value_param is not None else None
|
||||
else:
|
||||
params[key] = None
|
||||
parameters = params
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import datetime
|
||||
import json
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
from collections.abc import Mapping, Sequence
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
@@ -418,8 +417,6 @@ class PluginMigration:
|
||||
|
||||
logger.info("Uninstall plugins")
|
||||
|
||||
sys.exit(-1)
|
||||
|
||||
# get installation
|
||||
try:
|
||||
installation = manager.list_plugins(fake_tenant_id)
|
||||
|
||||
@@ -7,7 +7,7 @@ from sqlalchemy.orm import Session
|
||||
from configs import dify_config
|
||||
from core.helper.position_helper import is_filtered
|
||||
from core.model_runtime.utils.encoders import jsonable_encoder
|
||||
from core.plugin.entities.plugin import GenericProviderID
|
||||
from core.plugin.entities.plugin import GenericProviderID, ToolProviderID
|
||||
from core.plugin.manager.exc import PluginDaemonClientSideError
|
||||
from core.tools.builtin_tool.providers._positions import BuiltinToolProviderSort
|
||||
from core.tools.entities.api_entities import ToolApiEntity, ToolProviderApiEntity
|
||||
@@ -240,10 +240,7 @@ class BuiltinToolManageService:
|
||||
|
||||
# rewrite db_providers
|
||||
for db_provider in db_providers:
|
||||
try:
|
||||
GenericProviderID(db_provider.provider)
|
||||
except Exception:
|
||||
db_provider.provider = f"langgenius/{db_provider.provider}/{db_provider.provider}"
|
||||
db_provider.provider = str(ToolProviderID(db_provider.provider))
|
||||
|
||||
# find provider
|
||||
def find_provider(provider):
|
||||
|
||||
@@ -31,6 +31,7 @@ server {
|
||||
|
||||
location /e {
|
||||
proxy_pass http://plugin_daemon:5002;
|
||||
proxy_set_header Dify-Hook-Url $scheme://$host$request_uri;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { FC } from 'react'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type {
|
||||
ModelItem,
|
||||
@@ -9,11 +9,9 @@ import {
|
||||
CustomConfigurationStatusEnum,
|
||||
ModelTypeEnum,
|
||||
} from '../declarations'
|
||||
import type { PluginInfoFromMarketPlace } from '@/app/components/plugins/types'
|
||||
import { useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||
import ConfigurationButton from './configuration-button'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { PluginType } from '@/app/components/plugins/types'
|
||||
import {
|
||||
useModelModalHandler,
|
||||
useUpdateModelList,
|
||||
@@ -26,8 +24,7 @@ import StatusIndicators from './status-indicators'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { RiEqualizer2Line } from '@remixicon/react'
|
||||
import { fetchPluginInfoFromMarketPlace } from '@/service/plugins'
|
||||
import { fetchModelProviderModelList } from '@/service/common'
|
||||
import { useModelInList, usePluginInfo } from '@/service/use-plugins'
|
||||
|
||||
export type AgentModelTriggerProps = {
|
||||
open?: boolean
|
||||
@@ -66,43 +63,14 @@ const AgentModelTrigger: FC<AgentModelTriggerProps> = ({
|
||||
needsConfiguration,
|
||||
}
|
||||
}, [modelProviders, providerName])
|
||||
const [pluginInfo, setPluginInfo] = useState<PluginInfoFromMarketPlace | null>(null)
|
||||
const [isPluginChecked, setIsPluginChecked] = useState(false)
|
||||
const [installed, setInstalled] = useState(false)
|
||||
const [inModelList, setInModelList] = useState(false)
|
||||
const invalidateInstalledPluginList = useInvalidateInstalledPluginList()
|
||||
const handleOpenModal = useModelModalHandler()
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (modelId && currentProvider) {
|
||||
try {
|
||||
const modelsData = await fetchModelProviderModelList(`/workspaces/current/model-providers/${currentProvider?.provider}/models`)
|
||||
if (modelId && modelsData.data.find(item => item.model === modelId))
|
||||
setInModelList(true)
|
||||
}
|
||||
catch (error) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
if (providerName) {
|
||||
const parts = providerName.split('/')
|
||||
const org = parts[0]
|
||||
const name = parts[1]
|
||||
try {
|
||||
const pluginInfo = await fetchPluginInfoFromMarketPlace({ org, name })
|
||||
if (pluginInfo.data.plugin.category === PluginType.model)
|
||||
setPluginInfo(pluginInfo.data.plugin)
|
||||
}
|
||||
catch (error) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
setIsPluginChecked(true)
|
||||
})()
|
||||
}, [providerName, modelId, currentProvider])
|
||||
const { data: inModelList = false } = useModelInList(currentProvider, modelId)
|
||||
const { data: pluginInfo, isLoading: isPluginLoading } = usePluginInfo(providerName)
|
||||
|
||||
if (modelId && !isPluginChecked)
|
||||
if (modelId && isPluginLoading)
|
||||
return <Loading />
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { FC } from 'react'
|
||||
import { RiArrowDownSLine } from '@remixicon/react'
|
||||
import { RiEqualizer2Line } from '@remixicon/react'
|
||||
import { CubeOutline } from '@/app/components/base/icons/src/vender/line/shapes'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
import { useTranslation } from 'react-i18next'
|
||||
type ModelTriggerProps = {
|
||||
open: boolean
|
||||
className?: string
|
||||
@@ -11,6 +11,7 @@ const ModelTrigger: FC<ModelTriggerProps> = ({
|
||||
open,
|
||||
className,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
@@ -24,13 +25,13 @@ const ModelTrigger: FC<ModelTriggerProps> = ({
|
||||
</div>
|
||||
<div
|
||||
className='text-[13px] text-text-tertiary truncate'
|
||||
title='Select model'
|
||||
title='Configure model'
|
||||
>
|
||||
Select model
|
||||
{t('plugin.detailPanel.configureModel')}
|
||||
</div>
|
||||
</div>
|
||||
<div className='shrink-0 flex items-center justify-center w-4 h-4'>
|
||||
<RiArrowDownSLine className='w-3.5 h-3.5 text-text-tertiary' />
|
||||
<RiEqualizer2Line className='w-3.5 h-3.5 text-text-tertiary' />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useUpdateModelProviders } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import { useModelList } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||
import { useInvalidateAllBuiltInTools, useInvalidateAllToolProviders } from '@/service/use-tools'
|
||||
@@ -8,7 +9,9 @@ import { PluginType } from '../../types'
|
||||
|
||||
const useRefreshPluginList = () => {
|
||||
const invalidateInstalledPluginList = useInvalidateInstalledPluginList()
|
||||
const updateModelProviders = useUpdateModelProviders()
|
||||
const { mutate: refetchLLMModelList } = useModelList(ModelTypeEnum.textGeneration)
|
||||
const { mutate: refetchEmbeddingModelList } = useModelList(ModelTypeEnum.textEmbedding)
|
||||
const { mutate: refetchRerankModelList } = useModelList(ModelTypeEnum.rerank)
|
||||
const { refreshModelProviders } = useProviderContext()
|
||||
|
||||
const invalidateAllToolProviders = useInvalidateAllToolProviders()
|
||||
@@ -31,8 +34,10 @@ const useRefreshPluginList = () => {
|
||||
|
||||
// model select
|
||||
if (PluginType.model.includes(manifest.category) || refreshAllType) {
|
||||
updateModelProviders()
|
||||
refreshModelProviders()
|
||||
refetchLLMModelList()
|
||||
refetchEmbeddingModelList()
|
||||
refetchRerankModelList()
|
||||
}
|
||||
|
||||
// agent select
|
||||
|
||||
@@ -87,10 +87,13 @@ const InstallByDSLList: FC<Props> = ({
|
||||
const failedIndex: number[] = []
|
||||
const nextPlugins = produce(pluginsRef.current, (draft) => {
|
||||
marketPlaceInDSLIndex.forEach((index, i) => {
|
||||
if (payloads[i])
|
||||
draft[index] = payloads[i]
|
||||
else
|
||||
failedIndex.push(index)
|
||||
if (payloads[i]) {
|
||||
draft[index] = {
|
||||
...payloads[i],
|
||||
version: payloads[i].version || payloads[i].latest_version,
|
||||
}
|
||||
}
|
||||
else { failedIndex.push(index) }
|
||||
})
|
||||
})
|
||||
setPlugins(nextPlugins)
|
||||
@@ -192,8 +195,8 @@ const InstallByDSLList: FC<Props> = ({
|
||||
key={index}
|
||||
checked={!!selectedPlugins.find(p => p.plugin_id === plugins[index]?.plugin_id)}
|
||||
onCheckedChange={handleSelect(index)}
|
||||
payload={plugins[index] as Plugin}
|
||||
version={(d as GitHubItemAndMarketPlaceDependency).value.version!}
|
||||
payload={plugin}
|
||||
version={(d as GitHubItemAndMarketPlaceDependency).value.version! || plugin?.version || ''}
|
||||
versionInfo={getVersionInfo(`${plugin?.org || plugin?.author}/${plugin?.name}`)}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -136,9 +136,10 @@ const InstallFromGitHub: React.FC<InstallFromGitHubProps> = ({ updatePayload, on
|
||||
setState(prevState => ({ ...prevState, step: InstallStepFromGitHub.uploadFailed }))
|
||||
}, [])
|
||||
|
||||
const handleInstalled = useCallback(() => {
|
||||
const handleInstalled = useCallback((notRefresh?: boolean) => {
|
||||
setState(prevState => ({ ...prevState, step: InstallStepFromGitHub.installed }))
|
||||
refreshPluginList(manifest)
|
||||
if (!notRefresh)
|
||||
refreshPluginList(manifest)
|
||||
setIsInstalling(false)
|
||||
onSuccess()
|
||||
}, [manifest, onSuccess, refreshPluginList, setIsInstalling])
|
||||
|
||||
@@ -24,7 +24,7 @@ type LoadedProps = {
|
||||
selectedPackage: string
|
||||
onBack: () => void
|
||||
onStartToInstall?: () => void
|
||||
onInstalled: () => void
|
||||
onInstalled: (notRefresh?: boolean) => void
|
||||
onFailed: (message?: string) => void
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ const Loaded: React.FC<LoadedProps> = ({
|
||||
|
||||
const [isInstalling, setIsInstalling] = React.useState(false)
|
||||
const { mutateAsync: installPackageFromGitHub } = useInstallPackageFromGitHub()
|
||||
const { handleRefetch } = usePluginTaskList()
|
||||
const { handleRefetch } = usePluginTaskList(payload.category)
|
||||
const { check } = checkTaskStatus()
|
||||
|
||||
useEffect(() => {
|
||||
@@ -127,7 +127,7 @@ const Loaded: React.FC<LoadedProps> = ({
|
||||
onFailed(error)
|
||||
return
|
||||
}
|
||||
onInstalled()
|
||||
onInstalled(true)
|
||||
}
|
||||
catch (e) {
|
||||
if (typeof e === 'string') {
|
||||
|
||||
@@ -32,9 +32,10 @@ const ReadyToInstall: FC<Props> = ({
|
||||
}) => {
|
||||
const { refreshPluginList } = useRefreshPluginList()
|
||||
|
||||
const handleInstalled = useCallback(() => {
|
||||
const handleInstalled = useCallback((notRefresh?: boolean) => {
|
||||
onStepChange(InstallStep.installed)
|
||||
refreshPluginList(manifest)
|
||||
if (!notRefresh)
|
||||
refreshPluginList(manifest)
|
||||
setIsInstalling(false)
|
||||
}, [manifest, onStepChange, refreshPluginList, setIsInstalling])
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ type Props = {
|
||||
payload: PluginDeclaration
|
||||
onCancel: () => void
|
||||
onStartToInstall?: () => void
|
||||
onInstalled: () => void
|
||||
onInstalled: (notRefresh?: boolean) => void
|
||||
onFailed: (message?: string) => void
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ const Installed: FC<Props> = ({
|
||||
onCancel()
|
||||
}
|
||||
|
||||
const { handleRefetch } = usePluginTaskList()
|
||||
const { handleRefetch } = usePluginTaskList(payload.category)
|
||||
const handleInstall = async () => {
|
||||
if (isInstalling) return
|
||||
setIsInstalling(true)
|
||||
@@ -92,7 +92,7 @@ const Installed: FC<Props> = ({
|
||||
onFailed(error)
|
||||
return
|
||||
}
|
||||
onInstalled()
|
||||
onInstalled(true)
|
||||
}
|
||||
catch (e) {
|
||||
if (typeof e === 'string') {
|
||||
|
||||
@@ -54,9 +54,10 @@ const InstallFromMarketplace: React.FC<InstallFromMarketplaceProps> = ({
|
||||
return t(`${i18nPrefix}.installPlugin`)
|
||||
}, [isBundle, step, t])
|
||||
|
||||
const handleInstalled = useCallback(() => {
|
||||
const handleInstalled = useCallback((notRefresh?: boolean) => {
|
||||
setStep(InstallStep.installed)
|
||||
refreshPluginList(manifest)
|
||||
if (!notRefresh)
|
||||
refreshPluginList(manifest)
|
||||
setIsInstalling(false)
|
||||
}, [manifest, refreshPluginList, setIsInstalling])
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ type Props = {
|
||||
payload: PluginManifestInMarket | Plugin
|
||||
onCancel: () => void
|
||||
onStartToInstall?: () => void
|
||||
onInstalled: () => void
|
||||
onInstalled: (notRefresh?: boolean) => void
|
||||
onFailed: (message?: string) => void
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ const Installed: FC<Props> = ({
|
||||
check,
|
||||
stop,
|
||||
} = checkTaskStatus()
|
||||
const { handleRefetch } = usePluginTaskList()
|
||||
const { handleRefetch } = usePluginTaskList(payload.category)
|
||||
|
||||
useEffect(() => {
|
||||
if (hasInstalled && uniqueIdentifier === installedInfoPayload.uniqueIdentifier)
|
||||
@@ -106,7 +106,7 @@ const Installed: FC<Props> = ({
|
||||
onFailed(error)
|
||||
return
|
||||
}
|
||||
onInstalled()
|
||||
onInstalled(true)
|
||||
}
|
||||
catch (e) {
|
||||
if (typeof e === 'string') {
|
||||
|
||||
@@ -113,6 +113,7 @@ const DetailHeader = ({
|
||||
},
|
||||
payload: {
|
||||
type: PluginSource.github,
|
||||
category: detail.declaration.category,
|
||||
github: {
|
||||
originalPackageInfo: {
|
||||
id: detail.plugin_unique_identifier,
|
||||
@@ -287,6 +288,7 @@ const DetailHeader = ({
|
||||
isShowUpdateModal && (
|
||||
<UpdateFromMarketplace
|
||||
payload={{
|
||||
category: detail.declaration.category,
|
||||
originalPackageInfo: {
|
||||
id: detail.plugin_unique_identifier,
|
||||
payload: detail.declaration,
|
||||
|
||||
@@ -14,6 +14,7 @@ import { useGitHubReleases } from '../install-plugin/hooks'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { useModalContext } from '@/context/modal-context'
|
||||
import { useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||
import type { PluginType } from '@/app/components/plugins/types'
|
||||
|
||||
const i18nPrefix = 'plugin.action'
|
||||
|
||||
@@ -22,6 +23,7 @@ type Props = {
|
||||
installationId: string
|
||||
pluginUniqueIdentifier: string
|
||||
pluginName: string
|
||||
category: PluginType
|
||||
usedInApps: number
|
||||
isShowFetchNewVersion: boolean
|
||||
isShowInfo: boolean
|
||||
@@ -34,6 +36,7 @@ const Action: FC<Props> = ({
|
||||
installationId,
|
||||
pluginUniqueIdentifier,
|
||||
pluginName,
|
||||
category,
|
||||
isShowFetchNewVersion,
|
||||
isShowInfo,
|
||||
isShowDelete,
|
||||
@@ -67,6 +70,7 @@ const Action: FC<Props> = ({
|
||||
},
|
||||
payload: {
|
||||
type: PluginSource.github,
|
||||
category,
|
||||
github: {
|
||||
originalPackageInfo: {
|
||||
id: pluginUniqueIdentifier,
|
||||
|
||||
@@ -20,11 +20,9 @@ import Title from '../card/base/title'
|
||||
import Action from './action'
|
||||
import cn from '@/utils/classnames'
|
||||
import { API_PREFIX, MARKETPLACE_URL_PREFIX } from '@/config'
|
||||
import { useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||
import { useInvalidateAllBuiltInTools, useInvalidateAllToolProviders } from '@/service/use-tools'
|
||||
import { useSingleCategories } from '../hooks'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { useRenderI18nObject } from '@/hooks/use-i18n'
|
||||
import useRefreshPluginList from '@/app/components/plugins/install-plugin/hooks/use-refresh-plugin-list'
|
||||
|
||||
type Props = {
|
||||
className?: string
|
||||
@@ -39,10 +37,7 @@ const PluginItem: FC<Props> = ({
|
||||
const { categoriesMap } = useSingleCategories()
|
||||
const currentPluginID = usePluginPageContext(v => v.currentPluginID)
|
||||
const setCurrentPluginID = usePluginPageContext(v => v.setCurrentPluginID)
|
||||
const invalidateInstalledPluginList = useInvalidateInstalledPluginList()
|
||||
const invalidateAllToolProviders = useInvalidateAllToolProviders()
|
||||
const invalidateAllBuiltinTools = useInvalidateAllBuiltInTools()
|
||||
const { refreshModelProviders } = useProviderContext()
|
||||
const { refreshPluginList } = useRefreshPluginList()
|
||||
|
||||
const {
|
||||
source,
|
||||
@@ -60,13 +55,7 @@ const PluginItem: FC<Props> = ({
|
||||
}, [source, author])
|
||||
|
||||
const handleDelete = () => {
|
||||
invalidateInstalledPluginList()
|
||||
if (PluginType.model.includes(category))
|
||||
refreshModelProviders()
|
||||
if (PluginType.tool.includes(category)) {
|
||||
invalidateAllToolProviders()
|
||||
invalidateAllBuiltinTools()
|
||||
}
|
||||
refreshPluginList({ category } as any)
|
||||
}
|
||||
const getValueFromI18nObject = useRenderI18nObject()
|
||||
const title = getValueFromI18nObject(label)
|
||||
@@ -116,6 +105,7 @@ const PluginItem: FC<Props> = ({
|
||||
isShowDelete
|
||||
meta={meta}
|
||||
onDelete={handleDelete}
|
||||
category={category}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -29,8 +29,8 @@ const DebugInfo: FC = () => {
|
||||
popupContent={
|
||||
<>
|
||||
<div className='flex items-center gap-1 self-stretch'>
|
||||
<span className='flex flex-col justify-center items-start flex-grow flex-shrink-0 basis-0 text-text-secondary system-sm-semibold'>{t(`${i18nPrefix}.title`)}</span>
|
||||
<a href='' target='_blank' className='flex items-center gap-0.5 text-text-accent-light-mode-only cursor-pointer'>
|
||||
<span className='flex flex-col justify-center items-start grow shrink-0 basis-0 text-text-secondary system-sm-semibold'>{t(`${i18nPrefix}.title`)}</span>
|
||||
<a href='https://docs.dify.ai/plugins/quick-start/develop-plugins/debug-plugin' target='_blank' className='flex items-center gap-0.5 text-text-accent-light-mode-only cursor-pointer'>
|
||||
<span className='system-xs-medium'>{t(`${i18nPrefix}.viewDocs`)}</span>
|
||||
<RiArrowRightUpLine className='w-3 h-3' />
|
||||
</a>
|
||||
|
||||
@@ -151,6 +151,7 @@ export type Permissions = {
|
||||
}
|
||||
|
||||
export type UpdateFromMarketPlacePayload = {
|
||||
category: PluginType
|
||||
originalPackageInfo: {
|
||||
id: string
|
||||
payload: PluginDeclaration
|
||||
@@ -173,6 +174,7 @@ export type UpdateFromGitHubPayload = {
|
||||
|
||||
export type UpdatePluginPayload = {
|
||||
type: PluginSource
|
||||
category: PluginType
|
||||
marketPlace?: UpdateFromMarketPlacePayload
|
||||
github?: UpdateFromGitHubPayload
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ const UpdatePluginModal: FC<Props> = ({
|
||||
}
|
||||
|
||||
const [uploadStep, setUploadStep] = useState<UploadStep>(UploadStep.notStarted)
|
||||
const { handleRefetch } = usePluginTaskList()
|
||||
const { handleRefetch } = usePluginTaskList(payload.category)
|
||||
|
||||
const configBtnText = useMemo(() => {
|
||||
return ({
|
||||
|
||||
@@ -69,7 +69,7 @@ const ProviderList = () => {
|
||||
className='relative flex flex-col overflow-y-auto bg-background-body grow'
|
||||
>
|
||||
<div className={cn(
|
||||
'sticky top-0 flex justify-between items-center pt-4 px-12 pb-2 leading-[56px] z-20 flex-wrap gap-y-2',
|
||||
'sticky top-0 flex justify-between items-center pt-4 px-12 pb-2 leading-[56px] bg-background-body z-20 flex-wrap gap-y-2',
|
||||
currentProvider && 'pr-6',
|
||||
)}>
|
||||
<TabSliderNew
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { useCallback } from 'react'
|
||||
import type {
|
||||
ModelProvider,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import { fetchModelProviderModelList } from '@/service/common'
|
||||
import { fetchPluginInfoFromMarketPlace } from '@/service/plugins'
|
||||
import type {
|
||||
DebugInfo as DebugInfoTypes,
|
||||
Dependency,
|
||||
@@ -11,6 +16,7 @@ import type {
|
||||
PluginDetail,
|
||||
PluginInfoFromMarketPlace,
|
||||
PluginTask,
|
||||
PluginType,
|
||||
PluginsFromMarketplaceByInfoResponse,
|
||||
PluginsFromMarketplaceResponse,
|
||||
VersionInfo,
|
||||
@@ -18,6 +24,7 @@ import type {
|
||||
uploadGitHubResponse,
|
||||
} from '@/app/components/plugins/types'
|
||||
import { TaskStatus } from '@/app/components/plugins/types'
|
||||
import { PluginType as PluginTypeEnum } from '@/app/components/plugins/types'
|
||||
import type {
|
||||
PluginsSearchParams,
|
||||
} from '@/app/components/plugins/marketplace/types'
|
||||
@@ -31,6 +38,7 @@ import {
|
||||
import { useInvalidateAllBuiltInTools } from './use-tools'
|
||||
import usePermission from '@/app/components/plugins/plugin-page/use-permission'
|
||||
import { uninstallPlugin } from '@/service/plugins'
|
||||
import useRefreshPluginList from '@/app/components/plugins/install-plugin/hooks/use-refresh-plugin-list'
|
||||
|
||||
const NAME_SPACE = 'plugins'
|
||||
|
||||
@@ -367,10 +375,11 @@ export const useFetchPluginsInMarketPlaceByInfo = (infos: Record<string, any>[])
|
||||
}
|
||||
|
||||
const usePluginTaskListKey = [NAME_SPACE, 'pluginTaskList']
|
||||
export const usePluginTaskList = () => {
|
||||
export const usePluginTaskList = (category?: PluginType) => {
|
||||
const {
|
||||
canManagement,
|
||||
} = usePermission()
|
||||
const { refreshPluginList } = useRefreshPluginList()
|
||||
const {
|
||||
data,
|
||||
isFetched,
|
||||
@@ -383,8 +392,12 @@ export const usePluginTaskList = () => {
|
||||
refetchInterval: (lastQuery) => {
|
||||
const lastData = lastQuery.state.data
|
||||
const taskDone = lastData?.tasks.every(task => task.status === TaskStatus.success || task.status === TaskStatus.failed)
|
||||
if (taskDone)
|
||||
const taskAllFailed = lastData?.tasks.every(task => task.status === TaskStatus.failed)
|
||||
if (taskDone) {
|
||||
if (lastData?.tasks.length && !taskAllFailed)
|
||||
refreshPluginList(category ? { category } as any : undefined, !category)
|
||||
return false
|
||||
}
|
||||
|
||||
return 5000
|
||||
},
|
||||
@@ -443,3 +456,40 @@ export const useMutationCheckDependencies = () => {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const useModelInList = (currentProvider?: ModelProvider, modelId?: string) => {
|
||||
return useQuery({
|
||||
queryKey: ['modelInList', currentProvider?.provider, modelId],
|
||||
queryFn: async () => {
|
||||
if (!modelId || !currentProvider) return false
|
||||
try {
|
||||
const modelsData = await fetchModelProviderModelList(`/workspaces/current/model-providers/${currentProvider?.provider}/models`)
|
||||
return !!modelId && !!modelsData.data.find(item => item.model === modelId)
|
||||
}
|
||||
catch (error) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
enabled: !!modelId && !!currentProvider,
|
||||
})
|
||||
}
|
||||
|
||||
export const usePluginInfo = (providerName?: string) => {
|
||||
return useQuery({
|
||||
queryKey: ['pluginInfo', providerName],
|
||||
queryFn: async () => {
|
||||
if (!providerName) return null
|
||||
const parts = providerName.split('/')
|
||||
const org = parts[0]
|
||||
const name = parts[1]
|
||||
try {
|
||||
const response = await fetchPluginInfoFromMarketPlace({ org, name })
|
||||
return response.data.plugin.category === PluginTypeEnum.model ? response.data.plugin : null
|
||||
}
|
||||
catch (error) {
|
||||
return null
|
||||
}
|
||||
},
|
||||
enabled: !!providerName,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user