mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-09 20:50:58 +00:00
feat: code by huntun
This commit is contained in:
@@ -4,6 +4,11 @@ import PluginInstalledComponent, {
|
||||
} from '@/app/home/plugins/plugin-installed/PluginInstalledComponent';
|
||||
import MarketPage from '@/app/home/plugins/plugin-market/PluginMarketComponent';
|
||||
// import PluginSortDialog from '@/app/home/plugins/plugin-sort/PluginSortDialog';
|
||||
import PluginMarketComponent from '@/app/home/plugins/plugin-market/PluginMarketComponent';
|
||||
import MCPComponent, {
|
||||
MCPComponentRef,
|
||||
} from '@/app/home/plugins/mcp/MCPComponent';
|
||||
import MCPMarketComponent from '@/app/home/plugins/mcp-market/MCPMarketComponent';
|
||||
import styles from './plugins.module.css';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { Button } from '@/components/ui/button';
|
||||
@@ -46,20 +51,27 @@ enum PluginInstallStatus {
|
||||
|
||||
export default function PluginConfigPage() {
|
||||
const { t } = useTranslation();
|
||||
const [activeTab, setActiveTab] = useState('installed');
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
// const [sortModalOpen, setSortModalOpen] = useState(false);
|
||||
const [activeTab, setActiveTab] = useState('installed');
|
||||
const [installSource, setInstallSource] = useState<string>('local');
|
||||
const [installInfo, setInstallInfo] = useState<Record<string, any>>({}); // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
const [sortModalOpen, setSortModalOpen] = useState(false);
|
||||
// const [mcpModalOpen, setMcpModalOpen] = useState(false);
|
||||
const [mcpMarketInstallModalOpen, setMcpMarketInstallModalOpen] =
|
||||
useState(false);
|
||||
const [pluginInstallStatus, setPluginInstallStatus] =
|
||||
useState<PluginInstallStatus>(PluginInstallStatus.WAIT_INPUT);
|
||||
const [mcpInstallStatus, setMcpInstallStatus] = useState<PluginInstallStatus>(
|
||||
PluginInstallStatus.WAIT_INPUT,
|
||||
);
|
||||
const [installError, setInstallError] = useState<string | null>(null);
|
||||
const [mcpInstallError, setMcpInstallError] = useState<string | null>(null);
|
||||
const [githubURL, setGithubURL] = useState('');
|
||||
const [isDragOver, setIsDragOver] = useState(false);
|
||||
const [pluginSystemStatus, setPluginSystemStatus] =
|
||||
useState<ApiRespPluginSystemStatus | null>(null);
|
||||
const [statusLoading, setStatusLoading] = useState(true);
|
||||
const pluginInstalledRef = useRef<PluginInstalledComponentRef>(null);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -106,11 +118,17 @@ export default function PluginConfigPage() {
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
const [mcpGithubURL, setMcpGithubURL] = useState('');
|
||||
const pluginInstalledRef = useRef<PluginInstalledComponentRef>(null);
|
||||
const mcpComponentRef = useRef<MCPComponentRef>(null);
|
||||
|
||||
function handleModalConfirm() {
|
||||
installPlugin(installSource, installInfo as Record<string, any>); // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
}
|
||||
|
||||
function handleMcpModalConfirm() {
|
||||
installMcpServer(mcpGithubURL);
|
||||
}
|
||||
function installPlugin(
|
||||
installSource: string,
|
||||
installInfo: Record<string, any>, // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
@@ -291,6 +309,46 @@ export default function PluginConfigPage() {
|
||||
return renderPluginConnectionErrorState();
|
||||
}
|
||||
|
||||
function installMcpServer(url: string) {
|
||||
setMcpInstallStatus(PluginInstallStatus.INSTALLING);
|
||||
httpClient
|
||||
.installMCPServerFromGithub(url)
|
||||
.then((resp) => {
|
||||
const taskId = resp.task_id;
|
||||
|
||||
let alreadySuccess = false;
|
||||
console.log('taskId:', taskId);
|
||||
|
||||
// 每秒拉取一次任务状态
|
||||
const interval = setInterval(() => {
|
||||
httpClient.getAsyncTask(taskId).then((resp) => {
|
||||
console.log('task status:', resp);
|
||||
if (resp.runtime.done) {
|
||||
clearInterval(interval);
|
||||
if (resp.runtime.exception) {
|
||||
setMcpInstallError(resp.runtime.exception);
|
||||
setMcpInstallStatus(PluginInstallStatus.ERROR);
|
||||
} else {
|
||||
// success
|
||||
if (!alreadySuccess) {
|
||||
toast.success(t('mcp.installSuccess'));
|
||||
alreadySuccess = true;
|
||||
}
|
||||
setMcpGithubURL('');
|
||||
setMcpMarketInstallModalOpen(false);
|
||||
mcpComponentRef.current?.refreshServerList();
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 1000);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log('error when install mcp server:', err);
|
||||
setMcpInstallError(err.message);
|
||||
setMcpInstallStatus(PluginInstallStatus.ERROR);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${styles.pageContainer} ${isDragOver ? 'bg-blue-50' : ''}`}
|
||||
@@ -316,6 +374,9 @@ export default function PluginConfigPage() {
|
||||
{t('plugins.marketplace')}
|
||||
</TabsTrigger>
|
||||
)}
|
||||
<TabsTrigger value="mcp" className="px-6 py-4 cursor-pointer">
|
||||
MCP
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<div className="flex flex-row justify-end items-center">
|
||||
@@ -372,6 +433,19 @@ export default function PluginConfigPage() {
|
||||
}}
|
||||
/>
|
||||
</TabsContent>
|
||||
<TabsContent value="mcp">
|
||||
<MCPComponent ref={mcpComponentRef} />
|
||||
</TabsContent>
|
||||
<TabsContent value="mcp-market">
|
||||
<MCPMarketComponent
|
||||
askInstallServer={(githubURL) => {
|
||||
setMcpGithubURL(githubURL);
|
||||
setMcpMarketInstallModalOpen(true);
|
||||
setMcpInstallStatus(PluginInstallStatus.WAIT_INPUT);
|
||||
setMcpInstallError(null);
|
||||
}}
|
||||
/>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
<Dialog open={modalOpen} onOpenChange={setModalOpen}>
|
||||
@@ -456,6 +530,66 @@ export default function PluginConfigPage() {
|
||||
pluginInstalledRef.current?.refreshPluginList();
|
||||
}}
|
||||
/> */}
|
||||
|
||||
{/* MCP Server 安装对话框 */}
|
||||
{/* <Dialog
|
||||
open={mcpMarketInstallModalOpen}
|
||||
onOpenChange={setMcpMarketInstallModalOpen}
|
||||
>
|
||||
<DialogContent className="w-[500px] p-6">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-4">
|
||||
<GithubIcon className="size-6" />
|
||||
<span>{t('mcp.installFromGithub')}</span>
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
{mcpInstallStatus === PluginInstallStatus.WAIT_INPUT && (
|
||||
<div className="mt-4">
|
||||
<p className="mb-2">{t('mcp.onlySupportGithub')}</p>
|
||||
<Input
|
||||
placeholder={t('mcp.enterGithubLink')}
|
||||
value={mcpGithubURL}
|
||||
onChange={(e) => setMcpGithubURL(e.target.value)}
|
||||
className="mb-4"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{mcpInstallStatus === PluginInstallStatus.INSTALLING && (
|
||||
<div className="mt-4">
|
||||
<p className="mb-2">{t('mcp.installing')}</p>
|
||||
</div>
|
||||
)}
|
||||
{mcpInstallStatus === PluginInstallStatus.ERROR && (
|
||||
<div className="mt-4">
|
||||
<p className="mb-2">{t('mcp.installFailed')}</p>
|
||||
<p className="mb-2 text-red-500">{mcpInstallError}</p>
|
||||
</div>
|
||||
)}
|
||||
<DialogFooter>
|
||||
{mcpInstallStatus === PluginInstallStatus.WAIT_INPUT && (
|
||||
<>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setMcpMarketInstallModalOpen(false)}
|
||||
>
|
||||
{t('common.cancel')}
|
||||
</Button>
|
||||
<Button onClick={handleMcpModalConfirm}>
|
||||
{t('common.confirm')}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
{mcpInstallStatus === PluginInstallStatus.ERROR && (
|
||||
<Button
|
||||
variant="default"
|
||||
onClick={() => setMcpMarketInstallModalOpen(false)}
|
||||
>
|
||||
{t('common.close')}
|
||||
</Button>
|
||||
)}
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user