From bf026f70a4fa4c98eb84816ecb902d95a0139142 Mon Sep 17 00:00:00 2001 From: FinleyGe Date: Tue, 18 Nov 2025 11:35:35 +0800 Subject: [PATCH 01/12] feat: download count --- .../openapi/core/plugin/marketplace/api.ts | 1 + .../web/components/common/Icon/constants.ts | 1 + .../common/Icon/icons/common/downloadLine.svg | 3 + .../components/core/plugin/tool/ToolCard.tsx | 15 +- pnpm-lock.yaml | 133 ++++++++++-------- .../app/src/pages/config/tool/marketplace.tsx | 10 +- .../src/web/core/plugin/marketplace/api.ts | 3 + projects/marketplace/package.json | 19 +-- projects/marketplace/src/instrumentation.ts | 6 +- .../marketplace/src/pages/api/tool/detail.ts | 6 +- .../src/pages/api/tool/getDownloadUrl.ts | 28 ++++ .../marketplace/src/pages/api/tool/list.ts | 5 +- projects/marketplace/src/pages/index.tsx | 40 +++--- .../src/service/downloadCount/index.ts | 36 +++++ .../marketplace/src/service/mongo/index.ts | 133 ++++++++++++++++++ .../src/service/mongo/models/download.ts | 23 +++ projects/marketplace/src/service/tool/data.ts | 10 +- projects/marketplace/src/web/api.ts | 7 + 18 files changed, 377 insertions(+), 102 deletions(-) create mode 100644 packages/web/components/common/Icon/icons/common/downloadLine.svg create mode 100644 projects/marketplace/src/pages/api/tool/getDownloadUrl.ts create mode 100644 projects/marketplace/src/service/downloadCount/index.ts create mode 100644 projects/marketplace/src/service/mongo/index.ts create mode 100644 projects/marketplace/src/service/mongo/models/download.ts diff --git a/packages/global/openapi/core/plugin/marketplace/api.ts b/packages/global/openapi/core/plugin/marketplace/api.ts index 56e5f5dfe073..5446400d8250 100644 --- a/packages/global/openapi/core/plugin/marketplace/api.ts +++ b/packages/global/openapi/core/plugin/marketplace/api.ts @@ -12,6 +12,7 @@ export const MarketplaceToolListItemSchema = formatToolSimpleSchema.extend({ }); export type MarketplaceToolListItemType = ToolSimpleType & { downloadUrl: string; + downloadCount: number; }; export const MarketplaceToolDetailItemSchema = formatToolDetailSchema.extend({ diff --git a/packages/web/components/common/Icon/constants.ts b/packages/web/components/common/Icon/constants.ts index dbc136653c5a..cdc8095080c5 100644 --- a/packages/web/components/common/Icon/constants.ts +++ b/packages/web/components/common/Icon/constants.ts @@ -45,6 +45,7 @@ export const iconPaths = { 'common/disable': () => import('./icons/common/disable.svg'), 'common/downArrowFill': () => import('./icons/common/downArrowFill.svg'), 'common/download': () => import('./icons/common/download.svg'), + 'common/downloadLine': () => import('./icons/common/downloadLine.svg'), 'common/edit': () => import('./icons/common/edit.svg'), 'common/editor/resizer': () => import('./icons/common/editor/resizer.svg'), 'common/ellipsis': () => import('./icons/common/ellipsis.svg'), diff --git a/packages/web/components/common/Icon/icons/common/downloadLine.svg b/packages/web/components/common/Icon/icons/common/downloadLine.svg new file mode 100644 index 000000000000..f8400f11d9db --- /dev/null +++ b/packages/web/components/common/Icon/icons/common/downloadLine.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/web/components/core/plugin/tool/ToolCard.tsx b/packages/web/components/core/plugin/tool/ToolCard.tsx index af5556fedcd4..3952783cf0e1 100644 --- a/packages/web/components/core/plugin/tool/ToolCard.tsx +++ b/packages/web/components/core/plugin/tool/ToolCard.tsx @@ -7,7 +7,7 @@ import MyIcon from '../../../common/Icon'; import { parseI18nString } from '@fastgpt/global/common/i18n/utils'; import { PluginStatusEnum } from '@fastgpt/global/core/plugin/type'; -/* +/* 3 种使用场景: 1. admin 视角插件市场:显示是否安装,无状态,显示安装/卸载 2. team 视角资源库:显示是否安装,状态文本,以及安装/卸载 @@ -23,6 +23,7 @@ export type ToolCardItemType = { downloadUrl?: string; status?: number; installed?: boolean; + downloadCount: number; }; const ToolCard = ({ @@ -127,6 +128,9 @@ const ToolCard = ({ boxShadow: '0 4px 4px 0 rgba(19, 51, 107, 0.05), 0 0 1px 0 rgba(19, 51, 107, 0.08);', '& .install-button': { display: 'flex' + }, + '& .download-count': { + display: 'none' } }} > @@ -195,6 +199,15 @@ const ToolCard = ({ {`by ${item.author || systemTitle || 'FastGPT'}`} + {/*TODO: when statistics is ready*/} + {/* + + {!item.downloadCount + ? 0 + : item.downloadCount < 1000 + ? `${item.downloadCount}` + : `${(item.downloadCount / 1000).toFixed(1)}k`} + */} {mode === 'marketplace' ? ( - ) : ( - - )} + + + {mode === 'marketplace' ? ( + + ) : ( + + )} + + {/* Update button for admin mode when update is available */} + {item.update && mode === 'admin' && ( + + )} + ); diff --git a/packages/web/components/core/plugin/tool/ToolDetailDrawer.tsx b/packages/web/components/core/plugin/tool/ToolDetailDrawer.tsx index fcb0dc6a453b..c3a0d2806c07 100644 --- a/packages/web/components/core/plugin/tool/ToolDetailDrawer.tsx +++ b/packages/web/components/core/plugin/tool/ToolDetailDrawer.tsx @@ -163,6 +163,8 @@ const ToolDetailDrawer = ({ onClose, selectedTool, onToggleInstall, + onUpdate, + isUpdating, systemTitle, onFetchDetail, isLoading, @@ -172,6 +174,8 @@ const ToolDetailDrawer = ({ onClose: () => void; selectedTool: ToolCardItemType; onToggleInstall: (installed: boolean) => void; + onUpdate?: () => void; + isUpdating?: boolean; systemTitle?: string; onFetchDetail?: (toolId: string) => Promise; isLoading?: boolean; @@ -321,11 +325,12 @@ const ToolDetailDrawer = ({ {`by ${parentTool?.author || systemTitle || 'FastGPT'}`} - + + {selectedTool.update && onUpdate && mode !== 'marketplace' && ( + + )} {showPoint && ( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9ff84989a974..d0cc12b8dace 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -73,7 +73,7 @@ importers: version: 1.2.8 '@fastgpt-sdk/plugin': specifier: 0.2.15 - version: 0.2.15(@types/node@20.14.0) + version: link:../../../../../../Users/finley_ge/Projects/fastgpt-plugins/sdk axios: specifier: ^1.12.1 version: 1.12.1 @@ -2335,9 +2335,6 @@ packages: resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@fastgpt-sdk/plugin@0.2.15': - resolution: {integrity: sha512-z2JMoQ02gDHDM3feWemY10GyI9g0AH9g1IUAuqSfThkmPMhdLGsB4B6V6r2aSCUCb9FbdNqJblzriPYH9VtP9w==} - '@fastify/accept-negotiator@1.1.0': resolution: {integrity: sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ==} engines: {node: '>=14'} @@ -4082,17 +4079,6 @@ packages: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} - '@ts-rest/core@3.52.1': - resolution: {integrity: sha512-tAjz7Kxq/grJodcTA1Anop4AVRDlD40fkksEV5Mmal88VoZeRKAG8oMHsDwdwPZz+B/zgnz0q2sF+cm5M7Bc7g==} - peerDependencies: - '@types/node': ^18.18.7 || >=20.8.4 - zod: ^3.22.3 - peerDependenciesMeta: - '@types/node': - optional: true - zod: - optional: true - '@tsconfig/node10@1.0.11': resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} @@ -11490,9 +11476,6 @@ packages: zod@3.25.51: resolution: {integrity: sha512-TQSnBldh+XSGL+opiSIq0575wvDPqu09AqWe1F7JhUMKY+M91/aGlK4MhpVNO7MgYfHcVCB1ffwAUTJzllKJqg==} - zod@3.25.76: - resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - zod@4.1.11: resolution: {integrity: sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==} @@ -13056,14 +13039,6 @@ snapshots: '@eslint/js@8.57.1': {} - '@fastgpt-sdk/plugin@0.2.15(@types/node@20.14.0)': - dependencies: - '@fortaine/fetch-event-source': 3.0.6 - '@ts-rest/core': 3.52.1(@types/node@20.14.0)(zod@3.25.76) - zod: 3.25.76 - transitivePeerDependencies: - - '@types/node' - '@fastify/accept-negotiator@1.1.0': {} '@fastify/ajv-compiler@3.6.0': @@ -15081,11 +15056,6 @@ snapshots: '@trysound/sax@0.2.0': {} - '@ts-rest/core@3.52.1(@types/node@20.14.0)(zod@3.25.76)': - optionalDependencies: - '@types/node': 20.14.0 - zod: 3.25.76 - '@tsconfig/node10@1.0.11': {} '@tsconfig/node12@1.0.11': {} @@ -24549,8 +24519,6 @@ snapshots: zod@3.25.51: {} - zod@3.25.76: {} - zod@4.1.11: {} zod@4.1.12: {} diff --git a/projects/app/src/pages/api/core/plugin/admin/marketplace/installed.ts b/projects/app/src/pages/api/core/plugin/admin/marketplace/installed.ts index 6006318a3f1f..a6faa1b6e331 100644 --- a/projects/app/src/pages/api/core/plugin/admin/marketplace/installed.ts +++ b/projects/app/src/pages/api/core/plugin/admin/marketplace/installed.ts @@ -26,7 +26,10 @@ async function handler( const tools = await APIGetSystemToolList(); return { - ids: tools.map((tool) => tool.id.replace(`${AppToolSourceEnum.systemTool}-`, '')) + list: tools.map((tool) => ({ + id: tool.id.replace(`${AppToolSourceEnum.systemTool}-`, ''), + version: tool.version + })) }; } diff --git a/projects/app/src/pages/config/tool/marketplace.tsx b/projects/app/src/pages/config/tool/marketplace.tsx index c3b60c410527..9a8ab7b3822f 100644 --- a/projects/app/src/pages/config/tool/marketplace.tsx +++ b/projects/app/src/pages/config/tool/marketplace.tsx @@ -9,7 +9,7 @@ import MyBox from '@fastgpt/web/components/common/MyBox'; import MyIconButton from '@fastgpt/web/components/common/Icon/button'; import MyMenu from '@fastgpt/web/components/common/MyMenu'; import { useState, useMemo, useRef, useEffect, useCallback, useReducer } from 'react'; -import { useDebounce, useMount } from 'ahooks'; +import { useDebounce, useMount, useSet } from 'ahooks'; import ToolCard, { type ToolCardItemType } from '@fastgpt/web/components/core/plugin/tool/ToolCard'; import ToolTagFilterBox from '@fastgpt/web/components/core/plugin/tool/TagFilterBox'; import ToolDetailDrawer from '@fastgpt/web/components/core/plugin/tool/ToolDetailDrawer'; @@ -61,28 +61,6 @@ const useSearchParams = () => { return { searchText, tagIds, updateParams }; }; -type OperatingAction = { type: 'TRY_ADD'; toolId: string } | { type: 'REMOVE'; toolId: string }; - -const operatingReducer = (state: Set, action: OperatingAction): Set => { - if (action.type === 'TRY_ADD') { - if (state.has(action.toolId)) { - return state; - } - const newSet = new Set(state); - newSet.add(action.toolId); - return newSet; - } - if (action.type === 'REMOVE') { - if (!state.has(action.toolId)) { - return state; - } - const newSet = new Set(state); - newSet.delete(action.toolId); - return newSet; - } - return state; -}; - const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { const { t, i18n } = useTranslation(); const router = useRouter(); @@ -93,7 +71,8 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { const { searchText, tagIds, updateParams } = useSearchParams(); const [selectedTool, setSelectedTool] = useState(null); - const [operatingToolIds, dispatchOperating] = useReducer(operatingReducer, new Set()); + const [installingOrDeletingToolIds, installingOrDeletingToolIdsDispatch] = useSet(); + const [updatingToolIds, updatingToolIdsDispatch] = useSet(); const operatingPromisesRef = useRef>>(new Map()); // Type filter @@ -154,16 +133,27 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { } ); - const [installedPluginsMap, setInstalledPluginsMap] = useState>({}); + const [installedPluginsMap, setInstalledPluginsMap] = useState< + Record< + string, + { + installed: boolean; + version?: string; + } + > + >({}); useRequest2( async () => { - const { ids } = await getSystemInstalledPlugins({ type: 'tool' }); - const data = ids.reduce( - (acc, id) => { - acc[id] = true; + const { list } = await getSystemInstalledPlugins({ type: 'tool' }); + const data = list.reduce( + (acc, item) => { + acc[item.id] = { + installed: true, + version: item.version + }; return acc; }, - {} as Record + {} as Record ); setInstalledPluginsMap(data); }, @@ -189,19 +179,25 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { } const operationPromise = (async () => { - dispatchOperating({ type: 'TRY_ADD', toolId: tool.id }); + installingOrDeletingToolIdsDispatch.add(tool.id); try { await intallPluginWithUrl({ downloadUrls: [downloadUrl] }); - setInstalledPluginsMap((prev) => ({ ...prev, [tool.id]: true })); + setInstalledPluginsMap((prev) => ({ + ...prev, + [tool.id]: { + installed: true, + version: tools.find((t) => t.toolId === tool.id)?.version + } + })); if (selectedTool?.id === tool.id) { setSelectedTool((prev) => (prev ? { ...prev, status: 3 } : null)); } } finally { - dispatchOperating({ type: 'REMOVE', toolId: tool.id }); + installingOrDeletingToolIdsDispatch.remove(tool.id); operatingPromisesRef.current.delete(tool.id); } })(); @@ -213,6 +209,58 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { manual: true } ); + + const handleUpdateTool = useCallback( + async (tool: ToolCardItemType) => { + const existingPromise = operatingPromisesRef.current.get(tool.id); + if (existingPromise) { + await existingPromise; + return; + } + + const operationPromise = (async () => { + updatingToolIdsDispatch.add(tool.id); + + try { + // 获取下载 URL + const downloadUrl = await getMarketplaceDownloadURL(tool.id); + if (!downloadUrl) return; + + // 调用安装接口进行更新 + await intallPluginWithUrl({ + downloadUrls: [downloadUrl] + }); + + // 更新安装插件映射 + setInstalledPluginsMap((prev) => ({ + ...prev, + [tool.id]: { + installed: true, + version: tool.version + } + })); + + // 如果当前选中的工具是要更新的工具,更新其状态 + if (selectedTool?.id === tool.id) { + setSelectedTool((prev) => (prev ? { ...prev, status: 3 } : null)); + } + } finally { + updatingToolIdsDispatch.remove(tool.id); + operatingPromisesRef.current.delete(tool.id); + } + })(); + + operatingPromisesRef.current.set(tool.id, operationPromise); + await operationPromise; + }, + [ + updatingToolIdsDispatch, + selectedTool, + getMarketplaceDownloadURL, + intallPluginWithUrl, + setInstalledPluginsMap + ] + ); const { runAsync: handleDeleteTool } = useRequest2( async (tool: ToolCardItemType) => { const existingPromise = operatingPromisesRef.current.get(tool.id); @@ -222,17 +270,22 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { } const operationPromise = (async () => { - dispatchOperating({ type: 'TRY_ADD', toolId: tool.id }); + installingOrDeletingToolIdsDispatch.add(tool.id); try { await deletePkgPlugin({ toolId: tool.id }); - setInstalledPluginsMap((prev) => ({ ...prev, [tool.id]: false })); + setInstalledPluginsMap((prev) => ({ + ...prev, + [tool.id]: { + installed: false + } + })); if (selectedTool?.id === tool.id) { setSelectedTool((prev) => (prev ? { ...prev, status: 1 } : null)); } } finally { - dispatchOperating({ type: 'REMOVE', toolId: tool.id }); + installingOrDeletingToolIdsDispatch.remove(tool.id); operatingPromisesRef.current.delete(tool.id); } })(); @@ -272,7 +325,8 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { return ( tools ?.map((tool) => { - const isInstalled = !!installedPluginsMap[tool.toolId]; + const isInstalled = !!installedPluginsMap[tool.toolId]?.installed; + const update = installedPluginsMap[tool.toolId]?.version !== tool.version; return { id: tool.toolId, @@ -285,6 +339,7 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { return parseI18nString(currentTag?.tagName || '', i18n.language) || ''; }), installed: isInstalled, + update, downloadCount: tool.downloadCount }; }) @@ -600,15 +655,12 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { { - if (installed) { - handleInstallTool(tool); - } else { - handleDeleteTool(tool); - } - }} + isInstallingOrDeleting={installingOrDeletingToolIds.has(tool.id)} + isUpdating={updatingToolIds.has(tool.id)} + onInstall={() => handleInstallTool(tool)} + onDelete={() => handleDeleteTool(tool)} + onUpdate={() => handleUpdateTool(tool)} onClickCard={() => setSelectedTool(tool)} /> ); @@ -633,7 +685,9 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { handleInstallTool(selectedTool); } }} - isLoading={operatingToolIds.has(selectedTool.id)} + onUpdate={() => handleUpdateTool(selectedTool)} + isUpdating={updatingToolIds.has(selectedTool.id)} + isLoading={installingOrDeletingToolIds.has(selectedTool.id)} mode="admin" //@ts-ignore onFetchDetail={async (toolId: string) => await getMarketplaceToolDetail({ toolId })} diff --git a/projects/app/src/pages/dashboard/systemTool/index.tsx b/projects/app/src/pages/dashboard/systemTool/index.tsx index cb0af99595a5..5d680495ebc6 100644 --- a/projects/app/src/pages/dashboard/systemTool/index.tsx +++ b/projects/app/src/pages/dashboard/systemTool/index.tsx @@ -342,7 +342,7 @@ const ToolKitProvider = ({ MenuIcon }: { MenuIcon: JSX.Element }) => { item={tool} systemTitle={feConfigs?.systemTitle} mode="team" - onClickButton={(installed) => toggleInstall({ pluginId: tool.id, installed })} + onInstall={(installed) => toggleInstall({ pluginId: tool.id, installed })} onClickCard={() => setSelectedTool(tool)} isLoading={loadingPluginIds.has(tool.id)} /> diff --git a/projects/marketplace/src/pages/index.tsx b/projects/marketplace/src/pages/index.tsx index f3f688151b46..eb0f53795269 100644 --- a/projects/marketplace/src/pages/index.tsx +++ b/projects/marketplace/src/pages/index.tsx @@ -30,7 +30,6 @@ const ToolkitMarketplace = () => { const [searchText, setSearchText] = useState(''); const [selectedTagIds, setSelectedTagIds] = useState([]); const [selectedTool, setSelectedTool] = useState(null); - const [operatingToolId] = useState(null); const [isSearchExpanded, setIsSearchExpanded] = useState(false); const [showCompactSearch, setShowCompactSearch] = useState(false); const heroSectionRef = useRef(null); @@ -176,17 +175,23 @@ const ToolkitMarketplace = () => { }); }, [tools, i18n.language, toolTags]); - const onDownload = useCallback((toolId: string) => { - getDownloadURL(toolId).then((url) => { + const onDownload = useCallback(async (toolId: string) => { + try { + const url = await getDownloadURL(toolId); if (url) { + // 创建下载链接 const link = document.createElement('a'); link.href = url; link.download = ''; + link.style.display = 'none'; document.body.appendChild(link); link.click(); document.body.removeChild(link); } - }); + } catch (error) { + console.error('Download failed:', error); + // 可以在这里添加错误提示 + } }, []); // 使用 IntersectionObserver 监听英雄区域是否在视窗中 @@ -219,6 +224,8 @@ const ToolkitMarketplace = () => { <> {t('app:fastgpt_marketplace')} + + { { + onInstall={() => { onDownload(tool.id); }} onClickCard={() => setSelectedTool(tool)} From 3e61c0acbb98c2a068b6dc6c3ca5c099a64edf3d Mon Sep 17 00:00:00 2001 From: FinleyGe Date: Wed, 19 Nov 2025 12:36:11 +0800 Subject: [PATCH 03/12] fix: ui --- .../core/plugin/tool/ToolDetailDrawer.tsx | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/packages/web/components/core/plugin/tool/ToolDetailDrawer.tsx b/packages/web/components/core/plugin/tool/ToolDetailDrawer.tsx index c3a0d2806c07..dbdd1797c773 100644 --- a/packages/web/components/core/plugin/tool/ToolDetailDrawer.tsx +++ b/packages/web/components/core/plugin/tool/ToolDetailDrawer.tsx @@ -326,28 +326,38 @@ const ToolDetailDrawer = ({ {`by ${parentTool?.author || systemTitle || 'FastGPT'}`} - - {selectedTool.update && onUpdate && mode !== 'marketplace' && ( - - )} + {/* Determine if we have two buttons */} + {(() => { + const hasUpdateButton = selectedTool.update && onUpdate && mode !== 'marketplace'; + const buttonFlex = hasUpdateButton ? 1 : 1; // Both use flex=1, but when single button it fills the space + + return ( + <> + + {hasUpdateButton && ( + + )} + + ); + })()} {showPoint && ( From 316d8714b96d215e76897830695df64cf4ede42a Mon Sep 17 00:00:00 2001 From: FinleyGe Date: Wed, 19 Nov 2025 12:38:23 +0800 Subject: [PATCH 04/12] chore: update sdk verison --- packages/global/package.json | 2 +- pnpm-lock.yaml | 107 ++++++++++++++++++++++++++++++----- 2 files changed, 94 insertions(+), 15 deletions(-) diff --git a/packages/global/package.json b/packages/global/package.json index e0e775a420cd..4ca63017718f 100644 --- a/packages/global/package.json +++ b/packages/global/package.json @@ -2,7 +2,7 @@ "name": "@fastgpt/global", "version": "1.0.0", "dependencies": { - "@fastgpt-sdk/plugin": "0.2.15", + "@fastgpt-sdk/plugin": "0.2.16", "@apidevtools/swagger-parser": "^10.1.0", "@bany/curl-to-json": "^1.2.8", "axios": "^1.12.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d0cc12b8dace..0a8c3753b950 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -72,8 +72,8 @@ importers: specifier: ^1.2.8 version: 1.2.8 '@fastgpt-sdk/plugin': - specifier: 0.2.15 - version: link:../../../../../../Users/finley_ge/Projects/fastgpt-plugins/sdk + specifier: 0.2.16 + version: 0.2.16(@types/node@20.14.0) axios: specifier: ^1.12.1 version: 1.12.1 @@ -417,7 +417,7 @@ importers: version: 4.17.21 next: specifier: 14.2.32 - version: 14.2.32(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1) + version: 14.2.32(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1) next-i18next: specifier: 15.4.2 version: 15.4.2(i18next@23.16.8)(next@14.2.32(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) @@ -493,7 +493,7 @@ importers: version: 2.1.1(@chakra-ui/system@2.6.1(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(react@18.3.1))(react@18.3.1) '@chakra-ui/next-js': specifier: 2.4.2 - version: 2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.32(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1) + version: 2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.32(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1) '@chakra-ui/react': specifier: 2.10.7 version: 2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -595,10 +595,10 @@ importers: version: 5.1.3 next: specifier: 14.2.32 - version: 14.2.32(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1) + version: 14.2.32(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1) next-i18next: specifier: 15.4.2 - version: 15.4.2(i18next@23.16.8)(next@14.2.32(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + version: 15.4.2(i18next@23.16.8)(next@14.2.32(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) nprogress: specifier: ^0.2.0 version: 0.2.0 @@ -731,7 +731,7 @@ importers: version: 2.1.1(@chakra-ui/system@2.6.1(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(react@18.3.1))(react@18.3.1) '@chakra-ui/next-js': specifier: 2.4.2 - version: 2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.33(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1) + version: 2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.33(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1) '@chakra-ui/react': specifier: 2.10.7 version: 2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -758,10 +758,10 @@ importers: version: 8.12.1(socks@2.8.4) next: specifier: 14.2.33 - version: 14.2.33(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1) + version: 14.2.33(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1) next-i18next: specifier: 15.4.2 - version: 15.4.2(i18next@23.16.8)(next@14.2.33(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + version: 15.4.2(i18next@23.16.8)(next@14.2.33(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) react: specifier: 18.3.1 version: 18.3.1 @@ -2335,6 +2335,9 @@ packages: resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@fastgpt-sdk/plugin@0.2.16': + resolution: {integrity: sha512-tEpwtSLqPJCvvEk+KpdlgCl2N7n3m5ew2C9/hFKt+ahBY+eaU4WVrblJ6idSIImZ9lqOjOW4Mq7U1lO1mq06mQ==} + '@fastify/accept-negotiator@1.1.0': resolution: {integrity: sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ==} engines: {node: '>=14'} @@ -4079,6 +4082,17 @@ packages: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} + '@ts-rest/core@3.52.1': + resolution: {integrity: sha512-tAjz7Kxq/grJodcTA1Anop4AVRDlD40fkksEV5Mmal88VoZeRKAG8oMHsDwdwPZz+B/zgnz0q2sF+cm5M7Bc7g==} + peerDependencies: + '@types/node': ^18.18.7 || >=20.8.4 + zod: ^3.22.3 + peerDependenciesMeta: + '@types/node': + optional: true + zod: + optional: true + '@tsconfig/node10@1.0.11': resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} @@ -11476,6 +11490,9 @@ packages: zod@3.25.51: resolution: {integrity: sha512-TQSnBldh+XSGL+opiSIq0575wvDPqu09AqWe1F7JhUMKY+M91/aGlK4MhpVNO7MgYfHcVCB1ffwAUTJzllKJqg==} + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + zod@4.1.11: resolution: {integrity: sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==} @@ -12421,6 +12438,14 @@ snapshots: '@chakra-ui/system': 2.6.1(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(react@18.3.1) react: 18.3.1 + '@chakra-ui/next-js@2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.32(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1)': + dependencies: + '@chakra-ui/react': 2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@emotion/cache': 11.14.0 + '@emotion/react': 11.11.1(@types/react@18.3.1)(react@18.3.1) + next: 14.2.32(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1) + react: 18.3.1 + '@chakra-ui/next-js@2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.32(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1)': dependencies: '@chakra-ui/react': 2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -12429,12 +12454,12 @@ snapshots: next: 14.2.32(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1) react: 18.3.1 - '@chakra-ui/next-js@2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.33(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1)': + '@chakra-ui/next-js@2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.33(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1)': dependencies: '@chakra-ui/react': 2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@emotion/cache': 11.14.0 '@emotion/react': 11.11.1(@types/react@18.3.1)(react@18.3.1) - next: 14.2.33(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1) + next: 14.2.33(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1) react: 18.3.1 '@chakra-ui/object-utils@2.1.0': {} @@ -13039,6 +13064,14 @@ snapshots: '@eslint/js@8.57.1': {} + '@fastgpt-sdk/plugin@0.2.16(@types/node@20.14.0)': + dependencies: + '@fortaine/fetch-event-source': 3.0.6 + '@ts-rest/core': 3.52.1(@types/node@20.14.0)(zod@3.25.76) + zod: 3.25.76 + transitivePeerDependencies: + - '@types/node' + '@fastify/accept-negotiator@1.1.0': {} '@fastify/ajv-compiler@3.6.0': @@ -15056,6 +15089,11 @@ snapshots: '@trysound/sax@0.2.0': {} + '@ts-rest/core@3.52.1(@types/node@20.14.0)(zod@3.25.76)': + optionalDependencies: + '@types/node': 20.14.0 + zod: 3.25.76 + '@tsconfig/node10@1.0.11': {} '@tsconfig/node12@1.0.11': {} @@ -21178,6 +21216,18 @@ snapshots: transitivePeerDependencies: - supports-color + next-i18next@15.4.2(i18next@23.16.8)(next@14.2.32(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): + dependencies: + '@babel/runtime': 7.26.10 + '@types/hoist-non-react-statics': 3.3.6 + core-js: 3.41.0 + hoist-non-react-statics: 3.3.2 + i18next: 23.16.8 + i18next-fs-backend: 2.6.0 + next: 14.2.32(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1) + react: 18.3.1 + react-i18next: 14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next-i18next@15.4.2(i18next@23.16.8)(next@14.2.32(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.10 @@ -21190,7 +21240,7 @@ snapshots: react: 18.3.1 react-i18next: 14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - next-i18next@15.4.2(i18next@23.16.8)(next@14.2.33(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): + next-i18next@15.4.2(i18next@23.16.8)(next@14.2.33(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.10 '@types/hoist-non-react-statics': 3.3.6 @@ -21198,7 +21248,7 @@ snapshots: hoist-non-react-statics: 3.3.2 i18next: 23.16.8 i18next-fs-backend: 2.6.0 - next: 14.2.33(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1) + next: 14.2.33(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1) react: 18.3.1 react-i18next: 14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -21214,6 +21264,33 @@ snapshots: react: 19.1.1 react-i18next: 14.1.2(i18next@23.16.8)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + next@14.2.32(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1): + dependencies: + '@next/env': 14.2.32 + '@swc/helpers': 0.5.5 + busboy: 1.6.0 + caniuse-lite: 1.0.30001704 + graceful-fs: 4.2.11 + postcss: 8.4.31 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + styled-jsx: 5.1.1(@babel/core@7.26.10)(react@18.3.1) + optionalDependencies: + '@next/swc-darwin-arm64': 14.2.32 + '@next/swc-darwin-x64': 14.2.32 + '@next/swc-linux-arm64-gnu': 14.2.32 + '@next/swc-linux-arm64-musl': 14.2.32 + '@next/swc-linux-x64-gnu': 14.2.32 + '@next/swc-linux-x64-musl': 14.2.32 + '@next/swc-win32-arm64-msvc': 14.2.32 + '@next/swc-win32-ia32-msvc': 14.2.32 + '@next/swc-win32-x64-msvc': 14.2.32 + '@opentelemetry/api': 1.9.0 + sass: 1.85.1 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + next@14.2.32(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1): dependencies: '@next/env': 14.2.32 @@ -21268,7 +21345,7 @@ snapshots: - '@babel/core' - babel-plugin-macros - next@14.2.33(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1): + next@14.2.33(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1): dependencies: '@next/env': 14.2.33 '@swc/helpers': 0.5.5 @@ -24519,6 +24596,8 @@ snapshots: zod@3.25.51: {} + zod@3.25.76: {} + zod@4.1.11: {} zod@4.1.12: {} From a207ab3fb4708c3ebcc7cea95978b5c95d45300d Mon Sep 17 00:00:00 2001 From: FinleyGe Date: Wed, 19 Nov 2025 14:24:23 +0800 Subject: [PATCH 05/12] chore: update .env.template --- projects/marketplace/.env.template | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/projects/marketplace/.env.template b/projects/marketplace/.env.template index bf02052a515a..4b2163f916bc 100644 --- a/projects/marketplace/.env.template +++ b/projects/marketplace/.env.template @@ -1,2 +1,3 @@ S3_PREFIX=http://localhost:9000/fastgpt-plugins -AUTH_TOKEN=xxxx \ No newline at end of file +AUTH_TOKEN=xxxx +MONGODB_URI="mongodb://myusername:mypassword@localhost:27017/fastgpt?authSource=admin&directConnection=true" From 46193f284bd898d2b3e06da7818d2d7aa9bf23bc Mon Sep 17 00:00:00 2001 From: FinleyGe Date: Wed, 19 Nov 2025 16:13:30 +0800 Subject: [PATCH 06/12] chore: adjust --- .../components/core/plugin/tool/ToolCard.tsx | 8 +-- .../plugin/admin/marketplace/installed.ts | 1 + .../app/src/pages/config/tool/marketplace.tsx | 67 ++++--------------- .../src/pages/dashboard/systemTool/index.tsx | 5 +- 4 files changed, 22 insertions(+), 59 deletions(-) diff --git a/packages/web/components/core/plugin/tool/ToolCard.tsx b/packages/web/components/core/plugin/tool/ToolCard.tsx index 56ec4e6c8846..0258c907cb5b 100644 --- a/packages/web/components/core/plugin/tool/ToolCard.tsx +++ b/packages/web/components/core/plugin/tool/ToolCard.tsx @@ -18,7 +18,7 @@ export type ToolCardItemType = { status?: number; installed?: boolean; update?: boolean; - downloadCount: number; + downloadCount?: number; }; /** @@ -185,9 +185,9 @@ const ToolCard = ({ viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" - stroke-width="2" - stroke-linecap="round" - stroke-linejoin="round" + strokeWidth="2" + strokeLinecap="round" + strokeLinejoin="round" aria-hidden="true" > diff --git a/projects/app/src/pages/api/core/plugin/admin/marketplace/installed.ts b/projects/app/src/pages/api/core/plugin/admin/marketplace/installed.ts index a6faa1b6e331..aed3c1acea23 100644 --- a/projects/app/src/pages/api/core/plugin/admin/marketplace/installed.ts +++ b/projects/app/src/pages/api/core/plugin/admin/marketplace/installed.ts @@ -24,6 +24,7 @@ async function handler( const { type } = req.query; const tools = await APIGetSystemToolList(); + console.log(tools); return { list: tools.map((tool) => ({ diff --git a/projects/app/src/pages/config/tool/marketplace.tsx b/projects/app/src/pages/config/tool/marketplace.tsx index 9a8ab7b3822f..17fe2ea9c0f6 100644 --- a/projects/app/src/pages/config/tool/marketplace.tsx +++ b/projects/app/src/pages/config/tool/marketplace.tsx @@ -133,29 +133,13 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { } ); - const [installedPluginsMap, setInstalledPluginsMap] = useState< - Record< - string, - { - installed: boolean; - version?: string; - } - > - >({}); - useRequest2( + const { data: systemInstalledPlugins, runAsync: refreshInstalledPlugins } = useRequest2( async () => { const { list } = await getSystemInstalledPlugins({ type: 'tool' }); - const data = list.reduce( - (acc, item) => { - acc[item.id] = { - installed: true, - version: item.version - }; - return acc; - }, - {} as Record - ); - setInstalledPluginsMap(data); + return { + ids: new Set(list.map((item) => item.id)), + map: new Map(list.map((item) => [item.id, item])) + }; }, { manual: false @@ -185,13 +169,6 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { await intallPluginWithUrl({ downloadUrls: [downloadUrl] }); - setInstalledPluginsMap((prev) => ({ - ...prev, - [tool.id]: { - installed: true, - version: tools.find((t) => t.toolId === tool.id)?.version - } - })); if (selectedTool?.id === tool.id) { setSelectedTool((prev) => (prev ? { ...prev, status: 3 } : null)); @@ -199,6 +176,7 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { } finally { installingOrDeletingToolIdsDispatch.remove(tool.id); operatingPromisesRef.current.delete(tool.id); + await refreshInstalledPlugins(); } })(); operatingPromisesRef.current.set(tool.id, operationPromise); @@ -231,15 +209,6 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { downloadUrls: [downloadUrl] }); - // 更新安装插件映射 - setInstalledPluginsMap((prev) => ({ - ...prev, - [tool.id]: { - installed: true, - version: tool.version - } - })); - // 如果当前选中的工具是要更新的工具,更新其状态 if (selectedTool?.id === tool.id) { setSelectedTool((prev) => (prev ? { ...prev, status: 3 } : null)); @@ -253,14 +222,9 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { operatingPromisesRef.current.set(tool.id, operationPromise); await operationPromise; }, - [ - updatingToolIdsDispatch, - selectedTool, - getMarketplaceDownloadURL, - intallPluginWithUrl, - setInstalledPluginsMap - ] + [updatingToolIdsDispatch, selectedTool, getMarketplaceDownloadURL, intallPluginWithUrl] ); + const { runAsync: handleDeleteTool } = useRequest2( async (tool: ToolCardItemType) => { const existingPromise = operatingPromisesRef.current.get(tool.id); @@ -274,12 +238,6 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { try { await deletePkgPlugin({ toolId: tool.id }); - setInstalledPluginsMap((prev) => ({ - ...prev, - [tool.id]: { - installed: false - } - })); if (selectedTool?.id === tool.id) { setSelectedTool((prev) => (prev ? { ...prev, status: 1 } : null)); @@ -287,6 +245,7 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { } finally { installingOrDeletingToolIdsDispatch.remove(tool.id); operatingPromisesRef.current.delete(tool.id); + await refreshInstalledPlugins(); } })(); operatingPromisesRef.current.set(tool.id, operationPromise); @@ -325,8 +284,10 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { return ( tools ?.map((tool) => { - const isInstalled = !!installedPluginsMap[tool.toolId]?.installed; - const update = installedPluginsMap[tool.toolId]?.version !== tool.version; + const isInstalled = systemInstalledPlugins?.ids.has(tool.toolId); + const update = !isInstalled + ? false + : systemInstalledPlugins?.map.get(tool.toolId)?.version !== tool.version; return { id: tool.toolId, @@ -348,7 +309,7 @@ const ToolkitMarketplace = ({ marketplaceUrl }: { marketplaceUrl: string }) => { return !tool.installed; }) || [] ); - }, [tools, installedPluginsMap, i18n.language, allTags, installedFilter]); + }, [tools, i18n.language, allTags, installedFilter, systemInstalledPlugins]); if (toolsError && !loadingTools) { return ( diff --git a/projects/app/src/pages/dashboard/systemTool/index.tsx b/projects/app/src/pages/dashboard/systemTool/index.tsx index 5d680495ebc6..69be7cb22d4a 100644 --- a/projects/app/src/pages/dashboard/systemTool/index.tsx +++ b/projects/app/src/pages/dashboard/systemTool/index.tsx @@ -342,9 +342,10 @@ const ToolKitProvider = ({ MenuIcon }: { MenuIcon: JSX.Element }) => { item={tool} systemTitle={feConfigs?.systemTitle} mode="team" - onInstall={(installed) => toggleInstall({ pluginId: tool.id, installed })} + onInstall={() => toggleInstall({ pluginId: tool.id, installed: true })} + onDelete={() => toggleInstall({ pluginId: tool.id, installed: false })} onClickCard={() => setSelectedTool(tool)} - isLoading={loadingPluginIds.has(tool.id)} + isInstallingOrDeleting={loadingPluginIds.has(tool.id)} /> ); })} From 43e8d7d04a6d1362dc42ff3d081e1c93b99a857d Mon Sep 17 00:00:00 2001 From: FinleyGe Date: Thu, 20 Nov 2025 10:24:27 +0800 Subject: [PATCH 07/12] chore: remove console.log --- .../app/src/pages/api/core/plugin/admin/marketplace/installed.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/projects/app/src/pages/api/core/plugin/admin/marketplace/installed.ts b/projects/app/src/pages/api/core/plugin/admin/marketplace/installed.ts index aed3c1acea23..a6faa1b6e331 100644 --- a/projects/app/src/pages/api/core/plugin/admin/marketplace/installed.ts +++ b/projects/app/src/pages/api/core/plugin/admin/marketplace/installed.ts @@ -24,7 +24,6 @@ async function handler( const { type } = req.query; const tools = await APIGetSystemToolList(); - console.log(tools); return { list: tools.map((tool) => ({ From da9fcab20760331f2f5163d765caa47e9be5fdb9 Mon Sep 17 00:00:00 2001 From: FinleyGe Date: Thu, 20 Nov 2025 10:44:59 +0800 Subject: [PATCH 08/12] chore: adjust --- .../global/openapi/core/plugin/marketplace/api.ts | 8 ++------ .../web/components/core/plugin/tool/ToolCard.tsx | 6 +++--- projects/app/src/pages/config/tool/marketplace.tsx | 2 +- .../src/pages/api/tool/getDownloadUrl.ts | 13 +++++++------ .../marketplace/src/service/downloadCount/index.ts | 2 +- projects/marketplace/src/web/api.ts | 8 ++++---- 6 files changed, 18 insertions(+), 21 deletions(-) diff --git a/packages/global/openapi/core/plugin/marketplace/api.ts b/packages/global/openapi/core/plugin/marketplace/api.ts index 2eda041bf8a5..ebf5a1bccc86 100644 --- a/packages/global/openapi/core/plugin/marketplace/api.ts +++ b/packages/global/openapi/core/plugin/marketplace/api.ts @@ -7,11 +7,8 @@ const formatToolDetailSchema = z.object({}); const formatToolSimpleSchema = z.object({}); // Create intersection types for extended schemas -export const MarketplaceToolListItemSchema = formatToolSimpleSchema.extend({ - downloadUrl: z.string() -}); +export const MarketplaceToolListItemSchema = formatToolSimpleSchema; export type MarketplaceToolListItemType = ToolSimpleType & { - downloadUrl: string; downloadCount: number; }; @@ -19,8 +16,7 @@ export const MarketplaceToolDetailItemSchema = formatToolDetailSchema.extend({ readme: z.string().optional() }); export const MarketplaceToolDetailSchema = z.object({ - tools: z.array(MarketplaceToolDetailItemSchema), - downloadUrl: z.string() + tools: z.array(MarketplaceToolDetailItemSchema) }); // List diff --git a/packages/web/components/core/plugin/tool/ToolCard.tsx b/packages/web/components/core/plugin/tool/ToolCard.tsx index 0258c907cb5b..753a927c2a16 100644 --- a/packages/web/components/core/plugin/tool/ToolCard.tsx +++ b/packages/web/components/core/plugin/tool/ToolCard.tsx @@ -308,21 +308,21 @@ const ToolCard = ({ }} isLoading={isInstallingOrDeleting} {...(!isInstallingOrDeleting ? { display: 'none' } : {})} - disabled={isUpdating} + isDisabled={isUpdating} > {item.installed ? t('app:toolkit_uninstall') : t('app:toolkit_install')} )} {/* Update button for admin mode when update is available */} - {item.update && mode === 'admin' && ( + {item.update && mode === 'admin' && onUpdate && (