mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-03 12:34:37 +00:00
feat: successfully install
This commit is contained in:
@@ -233,8 +233,8 @@ export function SidebarDataProvider({
|
||||
const resp = await httpClient.getMCPServers();
|
||||
setMCPServers(
|
||||
resp.servers.map((server) => ({
|
||||
id: server.name,
|
||||
name: server.name,
|
||||
id: server.name, // Keep __ for API calls
|
||||
name: server.name.replace(/__/g, '/'), // Display with / for readability
|
||||
enabled: server.enable,
|
||||
runtimeStatus: server.runtime_info?.status,
|
||||
})),
|
||||
|
||||
@@ -39,7 +39,9 @@ export default function MCPDetailContent({ id }: { id: string }) {
|
||||
setDetailEntityName(t('mcp.createServer'));
|
||||
} else {
|
||||
const server = mcpServers.find((s) => s.id === id);
|
||||
setDetailEntityName(server?.name ?? id);
|
||||
// Convert __ back to / for display (since / is used as separator in stored names)
|
||||
const displayName = (server?.name ?? id).replace(/__/g, '/');
|
||||
setDetailEntityName(displayName);
|
||||
}
|
||||
return () => setDetailEntityName(null);
|
||||
}, [id, isCreateMode, mcpServers, setDetailEntityName, t]);
|
||||
|
||||
@@ -309,7 +309,7 @@ const MCPForm = forwardRef<MCPFormHandle, MCPFormProps>(function MCPForm(
|
||||
const server = resp.server ?? resp;
|
||||
|
||||
const formValues: FormValues = {
|
||||
name: server.name,
|
||||
name: server.name.replace(/__/g, '/'), // Convert __ back to / for display
|
||||
mode: server.mode,
|
||||
url: '',
|
||||
command: '',
|
||||
|
||||
@@ -33,7 +33,7 @@ import PluginMarketCardComponent from './plugin-market-card/PluginMarketCardComp
|
||||
import { PluginMarketCardVO } from './plugin-market-card/PluginMarketCardVO';
|
||||
import { getCloudServiceClientSync } from '@/app/infra/http';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PluginV4 } from '@/app/infra/entities/plugin';
|
||||
import { PluginV4, PluginV4Status } from '@/app/infra/entities/plugin';
|
||||
import { extractI18nObject } from '@/i18n/I18nProvider';
|
||||
import { toast } from 'sonner';
|
||||
import { ApiRespMarketplacePlugins } from '@/app/infra/entities/api';
|
||||
@@ -489,13 +489,44 @@ function MarketPageContent({
|
||||
|
||||
// 处理安装插件
|
||||
const handleInstallPlugin = useCallback(
|
||||
async (author: string, pluginName: string) => {
|
||||
async (cardVO: PluginMarketCardVO) => {
|
||||
try {
|
||||
// Fetch full plugin details to get PluginV4 object
|
||||
if (cardVO.type === 'mcp' || cardVO.type === 'skill') {
|
||||
// For MCP and Skill, directly pass the data - backend will fetch from Space
|
||||
const pluginV4: PluginV4 = {
|
||||
id: 0,
|
||||
plugin_id: `${cardVO.author}/${cardVO.pluginName}`,
|
||||
mcp_id: cardVO.type === 'mcp' ? `${cardVO.author}/${cardVO.pluginName}` : undefined,
|
||||
skill_id: cardVO.type === 'skill' ? `${cardVO.author}/${cardVO.pluginName}` : undefined,
|
||||
author: cardVO.author,
|
||||
name: cardVO.pluginName,
|
||||
label: { en_US: cardVO.label, zh_Hans: cardVO.label },
|
||||
description: { en_US: cardVO.description, zh_Hans: cardVO.description },
|
||||
icon: cardVO.iconURL,
|
||||
repository: cardVO.githubURL,
|
||||
tags: cardVO.tags || [],
|
||||
install_count: cardVO.installCount,
|
||||
latest_version: cardVO.version,
|
||||
components: cardVO.components || {},
|
||||
status: PluginV4Status.Live,
|
||||
type: cardVO.type,
|
||||
created_at: '',
|
||||
updated_at: '',
|
||||
};
|
||||
installPlugin(pluginV4);
|
||||
return;
|
||||
}
|
||||
|
||||
// For plugin type, fetch full details via API
|
||||
const response = await getCloudServiceClientSync().getPluginDetail(
|
||||
author,
|
||||
pluginName,
|
||||
cardVO.author,
|
||||
cardVO.pluginName,
|
||||
);
|
||||
if (!response?.plugin) {
|
||||
console.error('Failed to install plugin: plugin not found', { author: cardVO.author, pluginName: cardVO.pluginName });
|
||||
toast.error(t('market.installFailed'));
|
||||
return;
|
||||
}
|
||||
const pluginV4: PluginV4 = response.plugin;
|
||||
|
||||
// Call the install function passed from parent
|
||||
@@ -505,7 +536,7 @@ function MarketPageContent({
|
||||
toast.error(t('market.installFailed'));
|
||||
}
|
||||
},
|
||||
[plugins, installPlugin, t],
|
||||
[installPlugin, t],
|
||||
);
|
||||
|
||||
// 清理定时器
|
||||
|
||||
@@ -50,7 +50,7 @@ function RecommendationListRow({
|
||||
}: {
|
||||
list: RecommendationList;
|
||||
tagNames: Record<string, string>;
|
||||
onInstall: (author: string, pluginName: string) => void;
|
||||
onInstall: (cardVO: PluginMarketCardVO) => void;
|
||||
isLast: boolean;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
@@ -162,7 +162,7 @@ export function RecommendationLists({
|
||||
}: {
|
||||
lists: RecommendationList[];
|
||||
tagNames: Record<string, string>;
|
||||
onInstall: (author: string, pluginName: string) => void;
|
||||
onInstall: (cardVO: PluginMarketCardVO) => void;
|
||||
}) {
|
||||
if (!lists || lists.length === 0) return null;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ export default function PluginMarketCardComponent({
|
||||
tagNames = {},
|
||||
}: {
|
||||
cardVO: PluginMarketCardVO;
|
||||
onInstall?: (author: string, pluginName: string) => void;
|
||||
onInstall?: (cardVO: PluginMarketCardVO) => void;
|
||||
tagNames?: Record<string, string>;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
@@ -244,7 +244,7 @@ export default function PluginMarketCardComponent({
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (onInstall) {
|
||||
onInstall(cardVO.author, cardVO.pluginName);
|
||||
onInstall(cardVO);
|
||||
}
|
||||
}}
|
||||
className={`bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg shadow-sm flex items-center gap-2 transition-all duration-200 ${
|
||||
|
||||
@@ -804,7 +804,7 @@ export class BackendClient extends BaseHttpClient {
|
||||
}
|
||||
|
||||
public getMCPServer(serverName: string): Promise<ApiRespMCPServer> {
|
||||
return this.get(`/api/v1/mcp/servers/${serverName}`);
|
||||
return this.get(`/api/v1/mcp/servers/${encodeURIComponent(serverName)}`);
|
||||
}
|
||||
|
||||
public createMCPServer(server: MCPServer): Promise<AsyncTaskCreatedResp> {
|
||||
@@ -815,18 +815,18 @@ export class BackendClient extends BaseHttpClient {
|
||||
serverName: string,
|
||||
server: Partial<MCPServer>,
|
||||
): Promise<AsyncTaskCreatedResp> {
|
||||
return this.put(`/api/v1/mcp/servers/${serverName}`, server);
|
||||
return this.put(`/api/v1/mcp/servers/${encodeURIComponent(serverName)}`, server);
|
||||
}
|
||||
|
||||
public deleteMCPServer(serverName: string): Promise<AsyncTaskCreatedResp> {
|
||||
return this.delete(`/api/v1/mcp/servers/${serverName}`);
|
||||
return this.delete(`/api/v1/mcp/servers/${encodeURIComponent(serverName)}`);
|
||||
}
|
||||
|
||||
public toggleMCPServer(
|
||||
serverName: string,
|
||||
target_enabled: boolean,
|
||||
): Promise<AsyncTaskCreatedResp> {
|
||||
return this.put(`/api/v1/mcp/servers/${serverName}`, {
|
||||
return this.put(`/api/v1/mcp/servers/${encodeURIComponent(serverName)}`, {
|
||||
enable: target_enabled,
|
||||
});
|
||||
}
|
||||
@@ -835,7 +835,7 @@ export class BackendClient extends BaseHttpClient {
|
||||
serverName: string,
|
||||
serverData: object,
|
||||
): Promise<AsyncTaskCreatedResp> {
|
||||
return this.post(`/api/v1/mcp/servers/${serverName}/test`, serverData);
|
||||
return this.post(`/api/v1/mcp/servers/${encodeURIComponent(serverName)}/test`, serverData);
|
||||
}
|
||||
|
||||
public installMCPServerFromGithub(
|
||||
|
||||
Reference in New Issue
Block a user